2011-10-16 11 views
322

Czy istnieje konstrukcja foreach w języku Go? Czy mogę iterować po plastrze lub tablicy przy użyciu for?Czy w Go jest pętla foreach?

+1

Sprawdź: http://groups.google.com/group/golang-nuts/browse_thread/thread/e2966ccdfe910e14? pli = 1 – Kakashi

+1

Użycie 'range' w pętlach' for' jest również wspomniane w sekcji "Interlude about Types" (pod koniec) poradnika Go . – kostix

Odpowiedz

512

http://golang.org/doc/go_spec.html#For_statements

A „do” oświadczenie z „zasięg” klauzuli iteruje przez wszystkie wpisy tablicy, kawałek, sznurka lub mapy, lub wartości otrzymanych na kanale. Dla każdego wpisu przypisuje wartości iteracji do odpowiednich iteracji zmiennych, a następnie wykonuje blok.

Jako przykład:

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

Jeśli nie dbają o indeksie, można użyć _:

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

podkreślenia, _, jest blank identifier anonimowy symbol zastępczy.

+8

Prawdopodobnie warto powiedzieć, że _ nazywa się pustym identyfikatorem i po prostu ignoruje wartość zwracaną. –

8

Poniższy przykład ilustruje sposób użycia operatora range w pętli for do wykonania pętli 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; 
} 

Przykład iteruje po tablicy funkcji w celu ujednolicenia obsługi błędów dla funkcji. Kompletny przykład można znaleźć pod adresem Google playground.

PS: pokazuje również, że aparaty wiszące są złym pomysłem na czytelność kodu. Podpowiedź: warunek for kończy się tuż przed wywołaniem action(). To oczywiste, prawda?

+3

Dodaje ',' i jest bardziej przejrzyste tam, gdzie kończy się warunek 'for': http://play.golang.org/p/ pcRg6WdxBd - To jest pierwszy raz, kiedy znalazłem argument przeciwny do stylu "idź fmt", dzięki! – topskip

+0

@topskip oba mają wartość fmt valid; po prostu wybierz najlepszą :) –

+0

@FilipHaglund Nie jest ważne, czy jest prawidłowe. Chodzi o to, że IMO jest bardziej jasne, gdzie warunek dla kończy się w tym konkretnym przypadku powyżej. – topskip

65

iteracyjnego Tablica lub plaster:

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

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

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

iteracyjne mapę:

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

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

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

iteracyjne kanał:

for v := range theChan {} 

Odpowiednik:

for { 
    v := <-theChan 
} 
+4

Mimo że OP tylko pytał o użycie plastra, wolę tę odpowiedź, ponieważ większość będzie potrzebowała również innych zastosowań. – domoarrigato

+1

ważne rozróżnienie na temat użycia 'chan': odejście od kanału spowoduje wyjście z pętli, jeśli autor zamknie kanał w pewnym momencie. W 'for {v: = <-theChan}' _equivalent_, to * nie * zakończy się po zamknięciu kanału. Możesz to sprawdzić za pomocą drugiej zwracanej wartości 'ok'. [PRZYKŁAD TURYSTYCZNY] (https://tour.golang.org/concurrency/4) – colminator

+0

Myśląc tak samo, gdy go czytam, 'for {...}' oznacza nieskończoną pętlę. – Levit

6

Można w rzeczywistości korzystać range bez odwoływania To wartości zwracanych za pomocą for range przeciwko swoim rodzaju:

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

+2

Dobrze wiedzieć, ale w większości przypadków nie będzie to przydatne. – Sridhar

+0

Uzgodnione @Sridhar to całkiem niszowe miejsce. – robstarbuck

3

Poniżej znajduje się przykładowy kod na jak korzystać z foreach w języku golang

package main 

import (
    "fmt" 
) 

func main() { 

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

    for index,element := range arrayOne{ 

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

    } 

} 

To działający przykład: https://play.golang.org/p/LXptmH4X_0