I've read https://go.dev/blog/pipelines and there're two functions:
// move numbers into a channel
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
// square those numbers take from "in" channel
func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}
and inside main function
in := gen(2, 3)
// Distribute the sq work across two goroutines that both read from in.
c1 := sq(in)
c2 := sq(in)
I thought that sq
is just a normal function, so c1 must take all values from "in" channel and c2 is empty, but it was not.
So this mean a goroutine inside a function still can get out of that function scope and return to main routine to execute next command ?
You misunderstand the concept of goroutines here, you may want to look into A Tour of Go : Concurrency.
As explained “The gen
function starts a goroutine that sends the integers” and “The second stage, sq
,” also starts a goroutine that “receives integers” and “emits the square of each received integer”. Both gen
and sq
create a (result) channel to which the internally scheduled goroutines send integers and return this channel immediately without waiting for the goroutines to run.
So both gen
and sq
return immediately while the goroutines are only scheduled for execution, but not yet executed. (Note that this is the most likely execution order, nothing gives you any synchronization guarantees here)
This is probably not the best stuff to learn Go, you should write synchronous code first. See also “producer–consumer queue” in “Rethinking Classical Concurrency Patterns”.
Assume we would block before calling merge
: Since all channels are unbuffered (“sends and receives block until the other side is ready”) after starting the “Fan-out, fan-in” example the goroutine started by gen
eventually gets scheduled, sends two values and is then blocked trying to send the third value, while the goroutines started by sq
get scheduled, received one value each and are now blocked by trying to send the square to their respective out channel.
This so far has nothing to do with “scope”, The only thing that is captured by the goroutines scope is a channel variable.
When you execute this example on a machine with enough CPU cores all goroutines run in parallel. Note that when you call merge
and read the out channels fast enough the order could change.