Golang development: channel use

Channel is mainly used for communication between multiple goroutines

channel syntax

Channel is a reference type, and you need to use make to create a channel, as follows:
make(chan Type, [buffer])
chan Type The channel type
buffer is an optional parameter, which represents the size of the channel buffer (omitted, it means no buffer)
write to the channel Input data use <- symbol

q := make(chan bool)
q<-true

Reading data from the channel also uses the <- symbol, but the written channel is on the right, and the channel is on the left when reading. The meaning is consistent with the direction, one is data entering the channel, the other is data going out of the channel

 q := make(chan bool)
<-q

Use of buffered channels

We have been using unbuffered channels, and today we mainly learn about cached channels.
For an unbuffered channel, after writing data, there must be a goroutine that reads the data from the channel before writing, otherwise the program will panic.

func main() {
	ch := make(chan int)
	ch<-1
}

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:

A buffered channel can write data of the buffer size, and can read from the channel without a goroutine.

func main() {
	ch := make(chan int,2)
	ch<-1
	ch<-2
}


Process finished with exit code 0

The execution results are consistent with expectations.

Use scenarios for channels with buffer sizes

If we have a task that requires 10 goroutines to be scheduled for execution, as long as one goroutine is executed, the scheduling should end. Let's look at the pseudo code

func test(wg *sync.WaitGroup,ch chan int,i int) {
	fmt.Println("test code")
	ch<-i
}

func main() {
	fmt.Println("start",runtime.NumGoroutine())
	ch := make(chan int)
	wg := new(sync.WaitGroup)
	for i:=0;i<10;i++ {
		wg.Add(1)
		go test(wg,ch,i)
	}
	fmt.Println(<-ch)
	fmt.Println("end",runtime.NumGoroutine())
	wg.Done()
}

start 1
test code
9
end 10

Judging from the execution results, the 9th goroutine has finished executing first. The program also exited normally. But we see that with the main goroutine, there are a total of 11 goroutines in the memory. When the program exits, there are still 10 goroutines, minus one main goroutine, and there are 9 goroutines that have not exited. This is not allowed for the program. , May leak or long-term occupation of resources is not released.

But if we use a buffered channel, we can use the channel buffering mechanism to exit all goroutines normally.
Look at the code

func test(wg *sync.WaitGroup,ch chan int,i int) {
	ch<-i
}

func main() {
	fmt.Println("start",runtime.NumGoroutine())
	ch := make(chan int, 10)
	wg := new(sync.WaitGroup)
	for i:=0;i<10;i++ {
		wg.Add(1)
		go test(wg,ch,i)
	}
	fmt.Println(<-ch,"success")
	for i:= 0;i<9;i++ {
	 fmt.Println(<-ch)
	}
	fmt.Println("end",runtime.NumGoroutine())
	wg.Done()
}

start 1
0 success
1
2
4
3
5
6
7
8
9
end 1

Process finished with exit code 0

When printing success, the first goroutine has completed the task, and the data in the channel is read out in a loop 9 times to ensure that the created goroutine will not be blocked and can exit normally.

Guess you like

Origin blog.csdn.net/feifeixiang2835/article/details/108815418