Goにforeachループはありますか?


566

foreachGo言語の構成要素はありますか?を使用してスライスまたは配列を反復できますforか?



2
利用rangeにおけるforループはまた、囲碁チュートリアルの(その終わりに向かって)「アンインタールードの種類について」に記載されています。
kostix

回答:


851

https://golang.org/ref/spec#For_range

「範囲」句を含む「for」ステートメントは、配列、スライス、文字列、マップ、またはチャネルで受信した値のすべてのエントリを反復処理します。エントリごとに、対応する反復変数に反復値を割り当ててから、ブロックを実行します。

例として:

for index, element := range someSlice {
    // index is the index where we are
    // element is the element from someSlice for where we are
}

インデックスを気にしない場合は、次を使用できます_

for _, element := range someSlice {
    // element is the element from someSlice for where we are
}

下線_は、空白の識別子であり、匿名のプレースホルダーです。


7
この例でelementは、は要素の(コピー)です。これは要素自体ではありません。に割り当てることはできますがelement、これは基になるシーケンスには影響しません。
nobar 2018

PythonとCでは、ローカライズ用の関数としてアンダースコア(gettextなど)を使用することがよくあります。アンダースコアを使用すると、Goで問題が発生しますか?Goはローカライズに同じライブラリを使用しますか?
Sergiy Kolodyazhnyy 2018

3
@SergiyKolodyazhnyy Py docsによると、「(gettext)関数は通常_()、ローカル名前空間のようにエイリアスされています」とありますが、これは慣例によるものであり、ローカリゼーションライブラリの一部ではありません。アンダースコア_は有効なラベルであり、Go(およびPythonとScalaと他の言語)_では、使用しない戻り値に割り当てるのも慣例です。_この例のスコープは、forループの本体に制限されています。パッケージスコープの関数がある場合_は、forループのスコープ内でシャドウされます。ローカライズ用のパッケージはいくつかありますが_、関数名としての使用は見ていません。
ダボス、

150

Goには-にforeach似た構文があります。配列/スライス、マップ、チャネルをサポートしています。

配列またはスライスを反復処理します

// index and value
for i, v := range slice {}

// index only
for i := range slice {}

// value only
for _, v := range slice {}

マップを反復処理する:

// key and value
for key, value := range theMap {}

// key only
for key := range theMap {}

// value only
for _, value := range theMap {}

チャネルを反復処理する:

for v := range theChan {}

チャネルを反復処理することは、チャネルが閉じられるまでチャネルから受信することと同じです。

for {
    v, ok := <-theChan
    if !ok {
        break
    }
}

11
OPはスライスの使用法のみを要求しましたが、ほとんどが最終的に他の使用法も必要になるため、私はこの答えを好みます。
domoarigato

3
chan使用法に関する重要な違い:ある時点でライターがチャネルを閉じた場合、チャネルをまたぐ範囲はループを適切に終了します。でfor {v := <-theChan} 同等、それはなりませんチャネルの近くに終了します。これについては、2番目のok戻り値でテストできます。ツアーの例
colm.anseo 2017年

それを読むときにも同じように考えてfor { ... }、無限ループを表しています。
Levite 2017

13

次の例はrangeforループ内で演算子を使用してループを実装する方法を示していforeachます。

func PrintXml (out io.Writer, value interface{}) error {
    var data []byte
    var err error

    for _, action := range []func() {
        func () { data, err = xml.MarshalIndent(value, "", "  ") },
        func () { _, err = out.Write([]byte(xml.Header)) },
        func () { _, err = out.Write(data) },
        func () { _, err = out.Write([]byte("\n")) }} {
        action();
        if err != nil {
            return err
        }
    }
    return nil;
}

この例では、関数の配列を反復処理して、関数のエラー処理を統一しています。完全な例は、Googleの遊び場です。

PS:それはまた、中かっこをぶら下げることはコードの可読性にとって悪い考えであることも示しています。ヒント:for条件はaction()呼び出しの直前に終了します。明らかですよね?


3
追加,とどこそれは明確だfor状態の終了:play.golang.org/p/pcRg6WdxBd -これは実際に私は、カウンタ引数見つけたのは初めてであるgo fmtスタイルを、ありがとう!
topskip 2014

@topskipはどちらも有効です。最高のものを選んでください:)
Filip Haglund

@FilipHaglund有効であれば問題ありません。ポイントは、IMOの場合、上記の特定のケースでfor条件がどこで終了するかが明確になるということです。
topskip 2015年

9
私の意見では、この回答は対象を絞った質問に対して不当に複雑です。
AndreasHassing 2016

@AndreasHassing冗長性を導入せずに代わりにそれを行う方法?
1

10

実際には、型に対して使用することで、range戻り値を参照せずに使用できfor rangeます。

arr := make([]uint8, 5)
i,j := 0,0
for range arr {
    fmt.Println("Array Loop",i)
    i++
}

for range "bytes" {
    fmt.Println("String Loop",j)
    j++
}

https://play.golang.org/p/XHrHLbJMEd


3
知っておくと便利ですが、ほとんどの場合は役に立ちません
Sridhar

@Sridharが同意した、それはかなりニッチだ。
robstarbuck 2016

10

以下は、golangでforeachを使用する方法のサンプルコードです。

package main

import (
    "fmt"
)

func main() {

    arrayOne := [3]string{"Apple", "Mango", "Banana"}

    for index,element := range arrayOne{

        fmt.Println(index)
        fmt.Println(element)        

    }   

}

これは実行例ですhttps://play.golang.org/p/LXptmH4X_0


とても良い説明!
Darlan Dieterich

時々、それは最も役立つ最も単純な例です。ありがとう!私は他のコメンターからの最も難解な答えに対して何も持っていません—それらは確かに非常に慣用的なGoプログラミングの複雑さを示しています。最も簡単な例を使用してコアに追加します(これは機能し、なぜ機能するかは明らかです)。
グウィネス・ルウェリン

4

はい、範囲

forループの範囲形式は、スライスまたはマップを反復処理します。

スライスにまたがる場合、反復ごとに2つの値が返されます。1つ目はインデックスで、2つ目はそのインデックスにある要素のコピーです。

例:

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
    for i, v := range pow {
        fmt.Printf("2**%d = %d\n", i, v)
    }

    for i := range pow {
        pow[i] = 1 << uint(i) // == 2**i
    }
    for _, value := range pow {
        fmt.Printf("%d\n", value)
    }
}
  • _に割り当てることで、インデックスまたは値をスキップできます。
  • インデックスのみが必要な場合は、値を完全に削除します。

1

これは明白かもしれませんが、次のように配列をインライン化できます。

package main

import (
    "fmt"
)

func main() {
    for _, element := range [3]string{"a", "b", "c"} {
        fmt.Print(element)
    }
}

出力:

abc

https://play.golang.org/p/gkKgF3y5nmt

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.