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

type Friends struct { 
    friends []Friend 
} 

Mi piacerebbe fare Friends gamma-in grado, questo significa che, se ho una variabile di tipo my_friendsFriends, posso ciclo anche se con:Crea una struttura "adattabile alla portata"?

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

è possibile in Go?

+2

Potresti indicare un caso d'uso del mondo reale per questo? cioè, perché vuoi questo invece di 'range Friends.friends' o' range Friends.List() '(solo esempio)? –

+0

Esempio: dopo si aggiorna la lista a un elenco di famiglie (gruppi di amici) e non si desidera modificare il codice client esistente che funziona perfettamente bene iterando su singoli amici. – Stein

risposta

-1

Ad esempio,

var my_friends Friends 

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

Questa non è davvero una risposta alla domanda originale. – simonmenke

+1

@simonmenke si ma può rendere più chiaro che non c'è bisogno di ciò che viene chiesto da OP. –

9

Attenzione: Come deft_code menziona, questo codice perde un canale e un goroutine quando le interruzioni del ciclo. Non usare questo come modello generale.


In movimento, non c'è modo di fare un tipo arbitrario compatibile per range, come range supporta solo fette, array, canali e mappe.

È possibile scorrere i canali utilizzando range, che è utile se si desidera eseguire un'iterazione su dati generati dinamicamente senza dover utilizzare una slice o una matrice.

Ad esempio:

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

Questa è la cosa più vicina si può avere a fare qualcosa 'RANGEABLE'.

Quindi una pratica comune è definire un metodo Iter() o qualcosa di simile sul proprio tipo e passarlo a range.

Vedere the spec per ulteriori informazioni su range.

+2

Lo svantaggio ovviamente è che l'utilizzo dei canali qui non è efficiente se confrontato con l'intervallo su sezioni. Ogni lettura/scrittura di un canale può far passare il tempo di esecuzione a una goroutine diversa, quando nella maggior parte dei casi si può andare oltre una fetta senza essere preceduti da altre goroutine. –

+1

Questo è vero fino a quando la costruzione della fetta è proibitivamente costosa o altrimenti indesiderabile. Ad esempio, in [cbfs] (https://github.com/couchbaselabs/cbfs) a volte attraversano tutti i file (o file all'interno di un intervallo). Ce ne possono essere miliardi e richiede richieste in batch contro il database e cose divertenti come quelle. – Dustin

+2

Questo perde un canale e una goroutine se l'intervallo non viene iterato fino al completamento. La soluzione semplice alla perdita causa razze o serrature morte. Una soluzione completa e robusta è molto complessa e sottile. Il consenso sulla mailing list interna di Google è che questo è un antipattern. –

11

Ha Amici essere una struttura? Altrimenti semplicemente

type Friends []Friend 
+2

Penso che questa sia un'ottima risposta.Se 'Friends struct' ha solo il contenuto mostrato, allora definisci il tipo come' tipo Friends [] Friend'. Go può avere metodi su tipi come questo non solo su 'struct's, che è un po 'diverso dalla maggior parte delle lingue. –

+0

Questa è una buona risposta finché non hai bisogno di una struttura ... –