2011-10-16 17 views
322

¿Hay un constructo foreach en el idioma Go? ¿Puedo iterar sobre un sector o matriz usando for?¿Hay un bucle foreach en Go?

+1

echa un vistazo a: http://groups.google.com/group/golang-nuts/browse_thread/thread/e2966ccdfe910e14? pli = 1 – Kakashi

+1

El uso de 'range' en' for' loops también se menciona en la sección "Un interludio sobre tipos" (hacia su final) del tutorial de Go . – kostix

Respuesta

512

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

A "para" declaración con un "rango" itera Claus por todas las entradas de una matriz, rebanada, cuerda o mapa, o valores recibidos en un canal. Para cada entrada, asigna valores de iteración a las variables de iteración correspondientes y luego ejecuta el bloque.

A modo de ejemplo:

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

Si no se preocupan por el índice, puede utilizar _:

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

El subrayado, _, es el blank identifier, un anónimo marcador de posición

+8

Probablemente sea útil decir que _ se llama un identificador en blanco y simplemente ignora el valor de retorno –

8

El siguiente ejemplo muestra cómo usar el operador range en un bucle for para implementar un bucle 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; 
} 

El ejemplo repite una serie de funciones para unificar el manejo de errores para las funciones. Un ejemplo completo se encuentra en Google playground.

PD: también muestra que las abrazaderas colgantes son una mala idea para la legibilidad del código. Sugerencia: la condición for finaliza justo antes de la llamada action(). Obvio, ¿no?

+3

Agregue un ',' y está más claro donde termina la condición 'for': http://play.golang.org/p/ pcRg6WdxBd: esta es la primera vez que encuentro un argumento en contra para el estilo 'go fmt', ¡gracias! – topskip

+0

@topskip ambos son válidos; simplemente elija el mejor :) –

+0

@FilipHaglund No es el punto si es válido. El punto es que IMO está más claro donde termina la condición para ese caso particular anterior. – topskip

65

iterar sobre array o rebanada:

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

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

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

iterar sobre un mapa:

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

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

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

iterar sobre un canal:

for v := range theChan {} 

Equivalente a:

for { 
    v := <-theChan 
} 
+4

Aunque el OP solo solicitó el uso de sectores, prefiero esta respuesta, porque la mayoría también necesitará los otros usos. – domoarrigato

+1

distinción importante sobre el uso de 'chan': la variación de un canal saldrá con gracia del bucle si el escritor cierra el canal en algún momento. En el 'for {v: = <-theChan}' _equivalent_, * no * saldrá en el canal cerrado. Puede probar esto a través del segundo valor de retorno 'ok'. [TOUR EJEMPLO] (https://tour.golang.org/concurrency/4) – colminator

+0

Pensó lo mismo al leerlo, 'para {...}' representa un ciclo infinito. – Levit

6

de hecho, puede utilizar range sin hacer referencia Es valores de retorno mediante el uso de for range junto a su tipo:

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

Es bueno saberlo pero eso no va a ser útil en la mayoría de los casos – Sridhar

+0

De acuerdo @Sridhar es bastante nicho. – robstarbuck

3

A continuación se presenta el código de ejemplo de cómo utilizar foreach en golang

package main 

import (
    "fmt" 
) 

func main() { 

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

    for index,element := range arrayOne{ 

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

    } 

} 

Este es un ejemplo de ejecución https://play.golang.org/p/LXptmH4X_0