- 概要
- 基本形 (インデックス付き)
- 基本形 (foreach)
- 基本形 (whileループ)
- 無限ループ
- 単純に指定回数だけループ (Range Loop)
- スライス(Slice) をループ
- マップ (Map) をループ
- チャネル (Channel) をループ
- 参考資料
概要
以下、自分用のメモです。
他の言語で開発した後にGo触ると、たまに「この場合のループの仕方どうやるんだっけ??」ってなるので、自分用にここにメモメモ。
基本形 (インデックス付き)
他の言語でもある for (var i = 0; i < xxx; i++)
のやつ。
package loops import"github.com/devlights/gomy/output"// BasicForLoop は、他の言語でも同じように存在する基本的な for-loop についてのサンプルです.func BasicForLoop() error { var ( items = []string{ "go", "java", "dotnet", "python", "flutter", } ) // 他の言語と同じように Go にも インデックス 付きの for-loop があるfor i := 0; i < 5; i++ { output.Stdoutf("", "[%d] %s\n", i, items[i]) } returnnil }
実行すると以下のようになります。
$ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime-example"" ENTER EXAMPLE NAME: loops_basic_for_loop [Name]"loops_basic_for_loop"[0] go [1] java [2] dotnet [3] python [4] flutter [Elapsed]48.508µs
基本形 (foreach)
他の言語にもある foreach なループについて。
package loops import"github.com/devlights/gomy/output"// BasicForeach は、Go での foreach ループについてのサンプルです.func BasicForeach() error { var ( items = []string{ "go", "java", "dotnet", "python", "flutter", } ) for i, v := range items { output.Stdoutf("", "[%d] %s\n", i, v) } returnnil }
実行すると以下のようになります。
$ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime-example"" ENTER EXAMPLE NAME: loops_basic_foreach [Name]"loops_basic_foreach"[0] go [1] java [2] dotnet [3] python [4] flutter [Elapsed]83.908µs
基本形 (whileループ)
Go には、while (xxx) {}
な書き方は出来ません。ループは全部 for で記載します。
package loops import ( "github.com/devlights/gomy/output" ) // WhileLoop は、GoでのWhileループについてのサンプルです.func WhileLoop() error { // Go には、ループはすべて for で記載することになっている。// 他の言語にある while () {} は提供されていない。 count := 5for count > 0 { output.Stdoutl("[count]", count) count -= 1 } returnnil }
実行すると以下のようになります。
gitpod /workspace/try-golang $ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime-example"" ENTER EXAMPLE NAME: loops_while [Name]"loops_while_loop"[count]5[count]4[count]3[count]2[count]1[Elapsed]2.15111ms
無限ループ
Goでの無限ループの書き方はちょっと独特。ラベルを使うことが多いです。
package loops import ( "context""fmt""time" ) // InfiniteLoop は、無限ループのサンプルです.func InfiniteLoop() error { var ( mainCtx, mainCxl = context.WithCancel(context.Background()) procCtx, procCxl = context.WithTimeout(mainCtx, 3*time.Second) ) defer mainCxl() defer procCxl() // Go では 無限ループ は以下のように for {} とだけ書く LOOP: for { select { case<-time.After(200 * time.Millisecond): fmt.Print(".") case<-procCtx.Done(): break LOOP } } fmt.Println("") returnnil }
実行すると以下のようになります。
$ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime-example"" ENTER EXAMPLE NAME: loops_infinite [Name]"loops_infinite_loop" .............. (200ms毎に . が一つずつ出力されていきます)[Elapsed]3.000759326s
単純に指定回数だけループ (Range Loop)
たまに指定した回数分だけループしたいときがあります。インデックスもいらない。
可能な限りメモリの消費も少なくしたい場合は、以下のようにすると便利かも。
package loops import"github.com/devlights/gomy/output"// RangeLoop は、単純に指定回数ループするためのサンプルです.func RangeLoop() error { // 単純に指定回数だけループしたい場合、[]struct{} を作って// ループさせるのが効率が良い. struct{} はメモリを消費しない.forrangemake([]struct{}, 3) { output.Stdoutl("", "hello") } // インデックスが欲しい場合for i := rangemake([]struct{}, 3) { output.Stdoutf("", "[%d] hello\n", i) } returnnil }
実行すると以下のようになります。
$ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime-example"" ENTER EXAMPLE NAME: loops_range [Name]"loops_range_loop" hello hello hello [0] hello [1] hello [2] hello [Elapsed]96.172µs
元ネタは以下です。
私の場合は自分用に以下の関数とかを定義して使ったりしてます。
package iter // Range は、指定された回数分ループ可能な空スライスを生成して返します。//// 元ネタは https://github.com/bradfitz/iter/blob/master/iter.go です。func Range(n int) []struct{} { returnmake([]struct{}, n) } // RangeFn は、Range に処理関数を指定できるバージョンです。挙動は同じです。//// 処理中にエラーが発生した場合、内部ループはそこで停止し// (エラーが発生したインデックス, エラー) を返します。func RangeFn(n int, fn func(i int) error) (int, error) { for i := range Range(n) { err := fn(i) if err != nil { return i, err } } return -1, nil }
gomy/iter.go at master · devlights/gomy · GitHub
スライス(Slice) をループ
package loops import "github.com/devlights/gomy/output" // SliceLoop は、スライスのループについてのサンプルです. func SliceLoop() error { var ( items =[]string{"golang", "java", "dotnet", "python", }) // スライスの foreach は、インデックスと値 となる for i, v :=range items { output.Stdoutf("", "[%d] %s\n", i, v)}return nil }
実行すると以下のようになります。
$ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime-example"" ENTER EXAMPLE NAME: loops_slice [Name]"loops_slice_loop"[0] golang [1] java [2] dotnet [3] python [Elapsed]58.79µs
マップ (Map) をループ
package loops import "github.com/devlights/gomy/output" // MapLoop は、 map のループについてのサンプルです. func MapLoop() error { var ( m = map[string]string{"go": "fmt.Println", "java": "System.out.println", "dotnet": "Console.WriteLine", "python": "print", }) // map の ループ は、key, value の値が毎ターン取得できる for k, v :=range m { output.Stdoutf("", "[%s] %s\n", k, v)}return nil }
実行すると以下のようになります。
$ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime-example"" ENTER EXAMPLE NAME: loops_map [Name]"loops_map_loop"[go] fmt.Println [java] System.out.println [dotnet] Console.WriteLine [python]print[Elapsed]59.103µs
チャネル (Channel) をループ
package loops import"github.com/devlights/gomy/output"// ChannelLoop は、チャネルをループさせる場合のサンプルです.func ChannelLoop() error { var ( ch = make(chanstring) quit = make(chanstruct{}) items = []string{ "go", "java", "dotnet", "python", "flutter", } ) gofunc(ch chan<- string) { deferclose(ch) for _, v := range items { ch <- v } }(ch) gofunc(quit chan<- struct{}, ch <-chanstring) { deferclose(quit) // チャネルを foreach ループする場合, インデックスは付かないfor v := range ch { output.Stdoutl("", v) } }(quit, ch) <-quit returnnil }
実行すると以下のようになります。
$ make run go get -d ./... go run -race github.com/devlights/try-golang/cmd/trygolang -onetime-example"" ENTER EXAMPLE NAME: loops_channel [Name]"loops_channel_loop" go java dotnet python flutter [Elapsed]695.753µs
参考資料
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場