2012-10-15 39 views
6
type Friend struct { 
    name string 
    age int 
} 

type Friends struct { 
    friends []Friend 
} 

Tôi muốn làm Friends phạm vi-thể, có nghĩa là, nếu tôi có một biến my_friends với loại Friends, tôi có thể lặp dù nó với:Tạo cấu trúc "phạm vi có thể"?

for i, friend := range my_friends { 
    // bla bla 
} 

là nó có thể ở Gò?

+2

Bạn có thể nêu rõ trường hợp sử dụng thực tế cho điều này không? tức là, tại sao bạn muốn điều này thay vì 'phạm vi Friends.friends' hoặc' phạm vi Friends.List() '(ví dụ chỉ)? –

+0

Ví dụ: sau này bạn nâng cấp danh sách của mình lên danh sách hộ gia đình (nhóm bạn bè) và bạn không muốn thay đổi mã máy khách hiện tại hoạt động hoàn toàn tốt khi lặp lại từng người bạn. – Stein

Trả lời

-1

Ví dụ,

var my_friends Friends 

for i, friend := range my_friends.friends { 
    // bla bla 
} 
+1

Đây không thực sự là câu trả lời cho câu hỏi ban đầu. – simonmenke

+1

@simonmenke có nhưng nó có thể làm rõ hơn rằng không có nhu cầu cho những gì được hỏi bởi OP. –

9

Hãy coi chừng: Như deft_code đề cập, mã này bị rò rỉ một kênh và một goroutine khi phá vỡ vòng lặp. Không sử dụng mẫu này làm mẫu chung.


Trong đi, không có cách nào để làm cho một kiểu bất kỳ tương thích cho range, như range chỉ hỗ trợ lát, mảng, các kênh truyền hình và bản đồ.

Bạn có thể lặp qua các kênh bằng cách sử dụng range, điều này hữu ích nếu bạn muốn lặp qua dữ liệu được tạo động mà không phải sử dụng một lát hoặc mảng.

Ví dụ:

func Iter() chan *Friend { 
    c := make(chan *Friend) 
    go func() { 
     for i:=0; i < 10; i++ { 
     c <- newFriend() 
     } 
     close(c) 
    }() 
    return c 
} 

func main() { 
    // Iterate 
    for friend := range Iter() { 
    fmt.Println("A friend:", friend) 
    } 
} 

Đó là điều gần nhất bạn có thể phải làm một cái gì đó 'rangeable'.

Vì vậy, thông lệ phổ biến là xác định phương thức Iter() hoặc điều gì đó tương tự trên loại của bạn và chuyển nó đến range.

Xem the spec để đọc thêm trên range.

+2

Nhược điểm của khóa học là việc sử dụng các kênh ở đây không hiệu quả so với trên các lát cắt. Mỗi kênh đọc/ghi có thể gây ra thời gian chạy để chuyển sang một goroutine khác, khi trong hầu hết các trường hợp, bạn có thể trải rộng trên một lát mà không bị các goroutines khác chặn trước. –

+1

Điều này đúng cho đến khi xây dựng lát cắt là tốn kém hoặc không mong muốn. Ví dụ: trong [cbfs] (https://github.com/couchbaselabs/cbfs), đôi khi tôi duyệt qua tất cả các tệp (hoặc tệp trong một phạm vi). Có thể có hàng tỷ người trong số họ và nó đòi hỏi các yêu cầu theo đợt đối với cơ sở dữ liệu và những thứ thú vị như thế. – Dustin

+2

Điều này làm rò rỉ một kênh và một goroutine nếu phạm vi không được lặp lại để hoàn thành. Giải pháp đơn giản cho sự rò rỉ gây ra các cuộc đua hoặc các khóa chết. Một giải pháp mạnh mẽ hoàn chỉnh rất phức tạp và tinh tế. Sự đồng thuận về danh sách gửi thư Go nội bộ của Google là đây là một mẫu giả mạo. –

11

Bạn bè là cấu trúc? Nếu không, chỉ cần thực hiện

type Friends []Friend 
+2

Tôi nghĩ đây là một câu trả lời rất hay.Nếu 'Friends struct' chỉ có nội dung được hiển thị thì hãy định nghĩa kiểu là' type Friends [] Friend'. Go có thể có các phương thức trên các kiểu như thế này không chỉ trên 'struct', mà nó có một chút khác biệt so với hầu hết các ngôn ngữ. –

+0

Đây là câu trả lời hay, miễn là bạn không cần cấu trúc ... –

Các vấn đề liên quan