2015-02-19 12 views
5

Próbuję z kanałami Go i zmieszany z poniżej przykład funkcja GO blogu:Powracający kanały Golang

func gen(nums []int) <-chan int { 
out := make(chan int) 
go func() { 
    for _, n := range nums { 
     out <- n 
    } 
    close(out) 
}() 
fmt.Println("return statement is called ") 
return out 
} 

główne:

func main() { 
c := make(<-chan int) 
c = gen([]int{2, 3, 4, 5}) 

// Consume the output.//Print 2,3,4,5 
fmt.Println(<-c) 
fmt.Println(<-c) 
fmt.Println(<-c) 
fmt.Println(<-c) 
} 

kompletny kod: http://play.golang.org/p/Qh30wzo4m0

moje wątpliwości: 1.Moje zrozumienie było, po powrocie nazywa się funkcja zostanie zakończona i kanał wewnątrz tej funkcji nie ma więcej życia.Tutaj zwraca się tylko wezwanie raz. Ale zawartość Out kanału podjęte wiele razy.W tym przypadku jak jest faktyczny przepływ wykonania? Jestem nowy jednoczesnych programming.Kindly pomóc

Odpowiedz

4
out := make(chan int) 

To nie jest buforowane kanał, co oznacza out <- n będzie blok aż ktoś gdzieś czyta że kanałowe (fmt.Println(<-c) przychodzące)
(Patrz także " do golang channels maintain order „)

Więc powrót na końcu funkcji gen() nie oznacza dosłowne go func() jest zakończony (ponieważ wciąż czeka na czytelników do korzystania z zawartości kanału out).

Ale main funkcja coraz out kanału jako powrotu z gen() funkcji.
Jak można to uzyskać po zakończeniu działania gen()?

Fakt gen() kończy nie ma wpływu na jej zwróconej wartości (kolejność kanałów out): Celem „gen()” to do „wygenerowania” że out kanału.

main może używać out (jako zwróconą wartość gen()) długo po zakończeniu gen().

Dosłowne go func w ramach gen() nadal działa, nawet jeśli zakończono gen().

+0

, Dzięki za szybką reply.I dostał swój punkt, ale na zewnątrz kanału jest przekazywany do funkcji głównego wartości zwracanej przez gen() function.So gdy gen() kończy się Jak to jest możliwe? –

+1

gen może zostać zakończony, ale jego wewnętrzny literał go func pozostaje, jako niezależny goroutine. – VonC

+0

Zmienna 'c' w głównym jest powrotem funkcji gen(). Tak więc mówisz, że będzie ona wypełniona wartościami nawet po zakończeniu gen() z powodu rutyny na żywo wewnątrz gen() ... –

1

Ponieważ gen() odpala funkcję populacyjną kanału jako goroutine;

go func() { 
    for _, n := range nums { 
     out <- n 
    } 
    close(out) 
}() 

i blokuje, gdy pierwsza wartość jest wysyłana w kanale out, ponieważ nic nie jest jeszcze odbierania (niebuforowane blokują kanały na wysyłanie aż coś odbiera na nich), że goroutine nie kończy się, gdy funkcja gen() zwraca.

otrzymuje od c w main()

fmt.Println(<-c) 
... 

następnie spowodować goroutine rozpoczął w gen() zachować wypełniania kanału, ponieważ wyniki są odczytywane, a następnie ostatecznie main() powroty gdy powraca goroutine, bo nie ma nic pozostawione do wysłania na out, a pozostało nic do odebrania na c.

Również c := make(<-chan int) w main() jest zbędny, ponieważ gen() tworzy kanał i zwraca go.

Zobacz Playground

+0

@Internet Jestem jasny w twoim punkcie: "Gorgonina nie kończy się, gdy funkcja gen() powraca." Ale główna funkcja wychodząca z kanału jako funkcja powrotu z funkcji gen() .Jak można to uzyskać po tym, jak gen() zostanie zakończony? To jest moja wątpliwość ... przepraszam, jeśli zadaję głupie pytania, jestem nowy w tym ... –

+0

@faisalkk funkcja 'gen()' zwraca kanał, a następnie kończy się. Kanał nie jest "własnością" tej funkcji, jest tylko tworzony i zwracany (dla ilustracji, goroutine może być postrzegane jako oddzielna funkcja "tła", która jest "wyrzucana" przez użycie słowa kluczowego "go".) . W tym momencie funkcja 'gen()' jest wolna do zakończenia, a kanał może być używany przez inne funkcje. – Intermernet