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

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
主站蜘蛛池模板: 阳新县| 东兰县| 迁安市| 海伦市| 同江市| 宿松县| 云南省| 大化| 太康县| 涟源市| 洞口县| 武定县| 石台县| 麻栗坡县| 临洮县| 红原县| 望城县| 神池县| 大足县| 铁岭县| 视频| 高淳县| 南乐县| 鹤峰县| 松潘县| 绥阳县| 青河县| 汾西县| 绥滨县| 马鞍山市| 漳浦县| 九台市| 罗城| 鹤山市| 都昌县| 上饶市| 梁山县| 盐城市| 河北省| 巍山| 邻水|