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

type Friends struct { 
    friends []Friend 
} 

我想打Friends範圍,能,這意味着,如果我有一個變量my_friendsFriends類型,我可以循環使用雖:使結構「範圍」?

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

是可以進去嗎?

+2

你能說出一個真實世界的用例嗎?即,爲什麼你想要這個,而不是'範圍Friends.friends'或'範圍Friends.List()'(僅限示例)? –

+0

示例:稍後將列表升級到家庭列表(朋友組),並且您不希望更改現有的客戶端代碼,這些代碼完全適用於單個朋友。 – Stein

回答

-1

例如,

var my_friends Friends 

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

這不是真正的原始問題的答案。 – simonmenke

+1

@simonmenke是的,但它可以更清楚地表明OP不需要什麼。 –

9

當心:作爲deft_code提到,此代碼泄漏的信道和一個的goroutine當循環中斷。不要將其用作一般模式。


在走,沒有辦法作出range兼容任意類型, range只支持切片,數組,渠道和地圖。

您可以使用range來迭代通道,如果您想迭代動態生成的數據而無需使用片或數組,那麼這非常有用。

例如:

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) 
    } 
} 

這就是你可以做一些 'rangeable' 最接近。

因此,通常的做法是在您的類型上定義方法Iter()或類似的東西, 將其傳遞給range

請參閱the spec以進一步閱讀range

+2

當然不利的一面是,與跨越切片相比,在這裏使用頻道效率不高。每個通道的讀/寫都可能導致運行時切換到不同的goroutine,在大多數情況下,您可以在一個切片上進行切片而不會被其他goroutine搶佔。 –

+1

這是真實的,直到構造切片是昂貴的或其他不合需要的。例如,在[cbfs](https://github.com/couchbaselabs/cbfs)中,我有時會遍歷所有文件(或範圍內的文件)。可能有數十億個,它需要對數據庫的批量請求和有趣的東西。 – Dustin

+2

如果範圍沒有迭代到完成,這會泄漏通道和goroutine。泄漏的簡單解決方案導致比賽或死鎖。完整的強大解決方案非常複雜和微妙。 Google內部Go郵件列表的共識是這是一個反模式。 –

11

好友要成爲一個結構?否則簡單地做

type Friends []Friend 
+2

我認爲這是一個非常好的答案。如果「朋友結構」只包含顯示的內容,則將該類型定義爲「類型Friends []朋友」。 Go可以使用這種類型的方法,而不僅僅是'struct's,它與大多數語言有點不同。 –

+0

這是一個很好的答案,只要你不需要一個結構... –