Def demo_input_and_output ():
input = Yield ' What is the input? '
Yield ' input is:%s '% input
gen = Demo_input_and_output ()
print (Gen.next ())
print (Gen.send (42))
This code demonstrates the functionality of the Python generator. Can see yield at the same time do two operations, one is to send out the data "waht is the input", at the same time do the operation is to receive data input. And the operation that receives the data is a blocking operation, if the external call to next (that is, to pass none), or call Send (42) (that is, to pass the value of 42), then the blocking operation will wait.
That is to say, Python's generator has a channel of external communication for sending and receiving messages. That's what it says when you use go to simulate Python's generator.
Copy Code code as follows:
Package Main
Import "FMT"
Func Demoinputandoutput (Channel Chan string) {
Channel <-"What Is my input?"
Input: = <-Channel
Channel <-FMT. Sprintf ("Input is:%s", input)
}
Func Main () {
Channel: = Make (Chan string)
Go Demoinputandoutput (channel)
Fmt. PRINTLN (<-Channel)
Channel <-"42"
Fmt. PRINTLN (<-Channel)
}
This code is basically equivalent to the Python version. The implied channel becomes explicit in the go version. Yield became a channel <-operation, and immediately made a <-channel blocking read operation. This is the essence of yield.
The Go channel can also be used as a iterator for loops:
Copy Code code as follows:
package main
Import "FMT"
Func somegenerator () <-chan str ing {
channel: = Make (chan string)
go func () {
Channel <-"A"
FMT. Println ("After a")
channel <-"C"
FMT. Println ("After C")
channel <-"B"
FMT. Println (' after B ')
Close (channel)
} ()
return Channel
}
Func main () {
channel: = Somegenerator ()
; for Val: = Range Channel {
fmt. Println (val)
}
}
Unlike Python's yield, where the channel <-is not equivalent to yield, it goes down until it blocks. Effect is
Copy Code code as follows:
After a
A
C
After C
After B
B
This is not the same order as expected. Here does not have after a after C B are printed because channel default only one element of the buffer, so write a block. If you increase the buffer, then it works.
Copy Code code as follows:
The output becomes:
It can be seen that Goroutine is like an independent thread playing with itself, without waiting to be executed. If you want to simulate yield, add the synchronized operation shown (blocking the read signal from the channel):
Copy Code code as follows:
Package Main
Import "FMT"
Func somegenerator () Chan string {
Channel: = Make (Chan string)
Go func () {
Channel <-"a"
<-Channel
Fmt. Println ("After a")
Channel <-"C"
<-Channel
Fmt. Println ("After C")
Channel <-"B"
<-Channel
Fmt. Println ("after B")
Close (channel)
}()
Return Channel
}
Func Main () {
Channel: = Somegenerator ()
For Val: = Range Channel {
Fmt. Println (Val)
Channel <-""
}
}
The result of the output is
A after the
a
c after
c
b
Here we can see that Python's generator is like a Golang goroutine with a channel with no buffer. This results in a yield context switch each time a value is generated. Although the process context switch is inexpensive, it is not without cost. Such a design as Goroutine's buffered channel can allow a goroutine to generate some output at once and then block the wait, instead of producing an output that blocks the wait and then produces another output. Golang rocks!