Quantcast
Channel: いろいろ備忘録日記
Viewing all articles
Browse latest Browse all 1459

Goメモ-149 (Goでのループの書き方)

$
0
0

概要

以下、自分用のメモです。

他の言語で開発した後に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

元ネタは以下です。

github.com

私の場合は自分用に以下の関数とかを定義して使ったりしてます。

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

参考資料

tour.golang.org

golang.org


過去の記事については、以下のページからご参照下さい。

  • いろいろ備忘録日記まとめ

devlights.github.io

サンプルコードは、以下の場所で公開しています。

  • いろいろ備忘録日記サンプルソース置き場

github.com

github.com

github.com


Viewing all articles
Browse latest Browse all 1459

Trending Articles