2011-10-16 12 views
322

Có cấu trúc foreach bằng ngôn ngữ Go không? Tôi có thể lặp qua một lát hoặc mảng bằng cách sử dụng for không?Có vòng lặp foreach trong Go không?

+1

kiểm tra: http://groups.google.com/group/golang-nuts/browse_thread/thread/e2966ccdfe910e14? pli = 1 – Kakashi

+1

Việc sử dụng 'phạm vi' trong các vòng lặp' for' cũng được đề cập trong phần "Một Interlude about Types" (hướng tới phần cuối) của hướng dẫn Go . – kostix

Trả lời

512

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

A "cho" tuyên bố với một "phạm vi" lặp khoản thông qua tất cả các mục của một mảng, miếng, chuỗi hoặc bản đồ, hoặc các giá trị nhận được trên một kênh. Đối với mỗi mục nhập, nó gán giá trị lặp cho các biến lặp tương ứng và sau đó thực thi khối.

Như một ví dụ:

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

Nếu bạn không quan tâm đến các chỉ mục, bạn có thể sử dụng _:

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

Các dấu gạch dưới, _, là blank identifier, một ẩn danh trình giữ chỗ.

+8

Có thể hữu ích khi nói rằng _ được gọi là một định danh trống và nó chỉ bỏ qua giá trị trả về –

8

Ví dụ sau đây cho biết cách sử dụng toán tử range trong vòng lặp for để triển khai vòng lặp 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; 
} 

Ví dụ này lặp qua một mảng chức năng để thống nhất xử lý lỗi cho các chức năng. Một ví dụ hoàn chỉnh là tại số playground của Google.

PS: nó cũng cho thấy rằng treo niềng răng là một ý tưởng tồi cho khả năng đọc mã. Gợi ý: điều kiện for kết thúc ngay trước cuộc gọi action(). Rõ ràng, phải không?

+3

Thêm một ',' và nó rõ ràng hơn khi điều kiện 'for' kết thúc: http://play.golang.org/p/ pcRg6WdxBd - Đây thực sự là lần đầu tiên tôi tìm thấy một đối số truy cập cho kiểu 'go fmt', cảm ơn! – topskip

+0

@topskip cả hai đều có giá trị fmt hợp lệ; chỉ cần chọn một trong những tốt nhất :) –

+0

@ FilipHaglund Nó không phải là điểm nếu nó là hợp lệ. Vấn đề là IMO rõ ràng hơn khi điều kiện cho kết thúc trong trường hợp cụ thể ở trên. – topskip

65

lặp qua mảng hoặc lát:

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

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

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

lặp trên một đồ:

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

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

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

lặp trên một kênh:

for v := range theChan {} 

Tương đương với:

for { 
    v := <-theChan 
} 
+4

Mặc dù OP chỉ yêu cầu sử dụng slice, tôi thích câu trả lời này, bởi vì hầu hết cuối cùng sẽ cần các tập quán khác. – domoarrigato

+1

sự khác biệt quan trọng về việc sử dụng 'chan': trên một kênh sẽ thoát ra khỏi vòng lặp một cách duyên dáng nếu người viết đóng kênh tại một số điểm. Trong 'for {v: = <-theChan}' _equivalent_, nó sẽ * không * thoát trên kênh đóng. Bạn có thể kiểm tra điều này thông qua giá trị trả về 'ok' thứ hai. [VÍ DỤ TOUR] (https://tour.golang.org/concurrency/4) – colminator

+0

Nghĩ tương tự khi đọc nó, 'cho {...}' là viết tắt của một vòng lặp vô hạn. – Levit

6

Bạn có thể trên thực tế sử dụng range mà không cần tham khảo đó là giá trị trả lại bằng cách sử dụng for range chống lại kiểu của bạn:

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

Điều cần biết nhưng điều đó sẽ không hữu ích trong hầu hết các trường hợp – Sridhar

+0

Đồng ý @Sridhar nó khá thích hợp. – robstarbuck

3

Tiếp theo là các mã ví dụ cho cách để sử dụng foreach tại golang

package main 

import (
    "fmt" 
) 

func main() { 

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

    for index,element := range arrayOne{ 

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

    } 

} 

Đây là ví dụ đang chạy https://play.golang.org/p/LXptmH4X_0