- 概要
- 基本形 (インデックス付き)
- 基本形 (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]) } return nil }
実行すると以下のようになります。
$ 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) } return nil }
実行すると以下のようになります。
$ 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 := 5 for count > 0 { output.Stdoutl("[count]", count) count -= 1 } return nil }
実行すると以下のようになります。
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("") return nil }
実行すると以下のようになります。
$ 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{} はメモリを消費しない. for range make([]struct{}, 3) { output.Stdoutl("", "hello") } // インデックスが欲しい場合 for i := range make([]struct{}, 3) { output.Stdoutf("", "[%d] hello\n", i) } return nil }
実行すると以下のようになります。
$ 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{} { return make([]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(chan string) quit = make(chan struct{}) items = []string{ "go", "java", "dotnet", "python", "flutter", } ) go func(ch chan<- string) { defer close(ch) for _, v := range items { ch <- v } }(ch) go func(quit chan<- struct{}, ch <-chan string) { defer close(quit) // チャネルを foreach ループする場合, インデックスは付かない for v := range ch { output.Stdoutl("", v) } }(quit, ch) <-quit return nil }
実行すると以下のようになります。
$ 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
参考資料
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場