官术网_书友最值得收藏!

Regular channels

To declare a channel in Go, you simply use the make keyword, as follows:

myChannel := make(chan int)

In the preceding code, we created and initialized a channel called myChannel that can hold int values. This channel can then be used to send an int value from one goroutine to another.

Here is how to receive a value from a channel:

//myIntValue will host the value received from the channel
myIntValue := <-myChannel

Here is how to send a value to a channel:

myChannel <- 4

 

Whenever you execute a send or a receive operation on a regular Go channel, your goroutine will block until the value is fully sent or received. This simply means that if you send a value via a channel but there is no other goroutine waiting for it on the other end, your goroutine will block. On the other hand, if you are attempting to receive a value via a channel but there is no other goroutine sending it on the other end, your goroutine will block. This behavior ensures that your code is synchronized, your values are fresh and up to date, and avoids the numerous problems that you can typically face in other programming languages when you use locks.

Let's take a look at a complete program showcasing two goroutines communicating, in order to learn more about Go channels:

package main

import (
"fmt"
"time"
)

func runLoopSend(n int, ch chan int) {
for i := 0; i < n; i++ {
ch <- i
}
close(ch)
}

func runLoopReceive(ch chan int) {
for {
i, ok := <-ch
if !ok {
break
}
fmt.Println("Received value:", i)
}
}

func main() {
myChannel := make(chan int)
go runLoopSend(10, myChannel)
go runLoopReceive(myChannel)
time.Sleep(2 * time.Second)
}

In the preceding code, we created a channel called myChannel, which we then pass to two goroutines: runLoopSend() and runLoopReceive(). The runLoopSend() function will keep sending values to this channel, whereas the runLoopReceive() function will keep receiving values from this channel.

The preceding code will provide the following output:

Received value: 0 Received value: 1 Received value: 2 Received value: 3 Received value: 4 Received value: 5 Received value: 6 Received value: 7 Received value: 8 Received value: 9 

Let's first focus on runLoopSend() because there is a new concept that we are showcasing here. Take a look at the following code line:

close(ch)

This syntax can be used to close a channel. Once a channel is closed, you cannot send data to it anymore, otherwise, a panic will occur.

Now, let's take a look at runLoopReceive, particularly at this following line:

i, ok := <-ch

The preceding line is a special syntax to inspect whether a channel is closed. If the channel is not closed, the value of ok will be true, while i will get the value getting sent via the channel. On the other hand, if the channel is closed, ok will be false. In the runLoopReceive goroutine, we break out of the for loop if ok is false.

There is actually another, more elegant way to write this for loop:

  for {
i, ok := <-ch
if !ok {
break
}
fmt.Println("Received value:", i)
}

 

We can replace the preceding code with the following code:

  for i := range ch {
fmt.Println("Received value:", i)
}

The for..range syntax is allowed on channels as it allows you to keep receiving data from a channel until the channel gets closed. 

The output of the program will simply be as follows:

Received value: 0 Received value: 1 Received value: 2 Received value: 3 Received value: 4 Received value: 5 Received value: 6 Received value: 7 Received value: 8 Received value: 9
主站蜘蛛池模板: 珠海市| 丹棱县| 黄石市| 滦平县| 惠安县| 扶绥县| 洱源县| 中卫市| 华亭县| 元阳县| 喀喇沁旗| 厦门市| 冀州市| 新余市| 龙陵县| 张掖市| 陆河县| 饶平县| 图木舒克市| 哈尔滨市| 曲靖市| 东山县| 天水市| 大英县| 潼关县| 怀集县| 晋城| 章丘市| 洛川县| 南和县| 岳普湖县| 望都县| 婺源县| 德清县| 宝鸡市| 娄底市| 平和县| 宜春市| 七台河市| 宝鸡市| 斗六市|