The reason for exiting directly is because the main and fmt printing in our code are executed concurrently. If fmt prints data urgently before it comes, the outer loop has already ended. , and then exited directly.
So can this case be run? Let’s try it
You can see that an error has been reported at this time. The error means that a deadlock will occur when sending 1 to the channel.
Then go back to the previous picture.
As we have said above, channel is an interaction between goroutine and goroutine.
But in this case there is only one goroutine missing, so another goroutine is needed to receive it.
Now you should know how to start a goroutine.
In the above picture we newly opened another goroutine, and then used an infinite loop to accept the value sent by the channel and print it come out.
But you will find that we sent two pieces of data to the channel, but the printing result at this time has only one piece of data. But it’s better than what we started with, right!
You can understand the execution flow of the code. First, a 1 is sent to the channel, and then the first value is obtained in a loop and printed.
Then send data 2 to the channel, but exit directly before printing, which results in the phenomenon that only data 1 is displayed but not data 2.
You should already know how to solve this problem through Kaka’s description.
That is to add a delayed exit time to the function channelDome.
Pass channel as a parameter
As you can see above, go is followed by a closure function. The c used in this closure is the outer c used.
So is it possible to pass this c using parameters? The answer is yes.
Of course, other parameters can also be passed
#You can see from the above picture that not only the channel but also the id parameter is passed, and the code can also be directly optimized into the enclosed part. , that is, taking the value directly from the channel.
From As can be seen in the above figure, everyone has his own channel, and then distributes it. After distribution, everyone will receive their own received value and print it out.
Similarly, you can see that we have added a new for loop at line 26 to send data to the channel.
From the running results, you will find that the order of printing is confusing, such as the two values receive i and receive I.
Do you have any doubts at this time? When we send data to the channel, we send it in order! Then they must be received in order when receiving.
Since we are very sure that the data is sent in order, the problem can only occur with Printf.
Because Printf has IO and is scheduled by goroutine, then Printf at this time is out of order, but the received values will be printed out one by one.
Use channel as the return value
The cases in the previous sections are all created by channel and then used as parameter passed in.
Then this section will return the channel as a return value.
package mainimport (
"fmt"
"time")func createWorker(id int) chan int {
c := make(chan int)
go func() {
for {
fmt.Printf("Worker %d receive %c\n", id,
Copy after login
From here you can see that we will The function was changed to the createWorker function, because the channel is created directly in this function.
Then the value received by the channel is printed through a coroutine.
Let’s take a look at the running results
Through the running results, we can know that our code writing is still correct, but you can see how to use the channel returned at this time very intuitively
But if the code When the number is large, you don't know how to use this channel at all, and all this code needs to be simply modified.
Then what needs to be done is to tell people outside how to use it.
It can be known from the above code that data is sent to the channel, then in createWorker
The channel returned by the method should be marked
So the current code looks like this. We directly mark the direction of the return value channel of the createWorker method. The function is to send data.
Then when printing, it will be the receipt, which looks very intuitive.
After modifying the above two steps, you will find that createWorker
calls an error, Cannot use 'createWorker(i)' (type chanWhen you see the error, you should know that the two types are not equal.
After modification, you will find that the compilation is correct and no error message is reported.
Lets talk about concurrent programming in Go (1)也是ok的。
package mainimport (
"fmt"
"time")func createWorker(id int) chan
Copy after login
学习了这么久了,那么咔咔问你一个问题,这段代码执行会发生什么?
Yes, an error will occur, because as mentioned at the beginning of the article, to send data to a channel, you need to open another coroutine to receive the data.
Although the coroutine is said to be lightweight, after sending data, it is necessary to switch the coroutine to receive data, which is very resource intensive.
Then this is what I will explain to you in this section.
Create a channel that can have 3 buffers, and then send 3 data to the channel.
You can also know from the results of running at the same time that deadlock
is not occurring.
A question for you, what will happen if you send a data 4 to the buffer?
You are smart, you must have thought of the result, yes, reported itdeadlock
Then we use the previous worker to receive the channel data.
But you will find that the running result still does not print out the 1,2,3,4 sent in.
This question has been asked several times now. You can try to ask yourself how you should solve this situation.
Just add a delay time. By the way, I would like to explain to you that the previous case printed Letters, %c used for all formatting, now print numbers, so changed to %d, a small change.
Establishing a channel in this way has a certain effect on improving performance.
Have you discovered a problem so far, that is, when sending a channel, you don’t know when it has been sent.
Let’s look at this issue next.
Borrow the code from the previous case to continue the explanation.
What is inconsistent with the previous code is that we added close at the end. It should be noted that close is closed on the sender.
You will see that the running results are not satisfactory. You will find that although 1,2,3,4 are received.
But a lot of 0s were received below, but only one piece of data was captured in the screenshot.
Although the sender closes the channel, the worker will still receive the data when the channel is closed. This does not mean that the data will not be received after the channel is closed.
But when the sender sets channelle to close, the data received are all 0, that is, the value of the parameter c chan int passed by the worker method is 0. .
Now our channel is of type int, and we receive 0. Then if it is a string type, what is received is an empty string.
How long will this take? That is the one millisecond time we set.
If you were asked to change this program, do you have any ideas? If you have no idea, just sway with the rhythm of this click.
In the function worker, two values are used to receive, n is the channel c passed over. ok is to determine whether the value exists.
You can see the running results, and you will no longer receive 0 data.
In addition to this way of writing, there is a simpler way.
Persistence in learning, persistence in writing, and persistence in sharing are the beliefs that Kaka has always adhered to since its beginning. I hope that Kaka’s articles on the huge Internet can bring you a little bit of help. I’m Kaka, see you next time.