go (basic 02)-channel (channel)

1. The concept of channel

By using channels, data can also be sent from one end and received at the other end.

2. Definition of channel

All channels are associated with a type. Channels can only transport this type of data, while transporting other types of data is illegal.

chan T Indicates the  T type of channel.

The zero value of the channel  nil. Zero value of the channel is no use, it should be like on the map and sliced done, with  make defined channel. E.g:

a := make(chan int)
package main

import (
	"fmt"
)

func main() {
	var a chan int
	if a == nil {
		fmt.Println("channel a is nil, going to define it")
		a = make(chan int)
		fmt.Printf("Type of a is %T", a)
	}
}

operation result:

3. Channel transmission and reception

data := <- a   // 读取信道a,并将数据保存至data 
a <- data      // 将data数据写入信道a

Note: The transmission and reception of the channel is blocked.

package main

import (
	"fmt"
)

func hello(done chan bool) {
	fmt.Println("Hello world goroutine")

	done <- true
}

func main() {
	done := make(chan bool)  //创建信道

	go hello(done)
	<-done
	fmt.Println("main function")
}

operation result:

4. Deadlock

Causes:

1) One go goroutine sends data, no other goroutine receives data

2) A go goroutine is waiting to receive data, no other goroutines are sending data

package main

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

Results of the:

5. One-way channel

Create a channel that can only send data:

package main

import "fmt"

func sendData(sendch chan<- int) {
	sendch <- 10
}

func main() {
	sendch := make(chan<- int) //创建一个只发送信道

	go sendData(sendch)
	fmt.Println(<-sendch)      //error:此处无法读取
}

Results of the:

6. Channel closed

The data sender can close the channel and notify the receiver that no more data is sent over this channel.

When receiving data from the channel, the receiver can use one more variable to check whether the channel has been closed.

v, ok := <- ch   //ok为false,则为读取一个关闭的信道
package main

import (
	"fmt"
)

func producer(chnl chan int) {
	for i := 0; i < 10; i++ {
		chnl <- i
	}
	close(chnl)  //close为关闭信道 
}

func main() {
	ch := make(chan int)
	go producer(ch)
	for {
		v, ok := <-ch
		if ok == false {
			break  //信道关闭 直接跳出循环
		}
		fmt.Println("Received ", v, ok)
	}
}

Results of the:

Note: The for range loop is used to receive data from the channel before the channel is closed.

package main

import (
	"fmt"
)

func producer(chnl chan int) {
	for i := 0; i < 10; i++ {
		chnl <- i
	}
	close(chnl)
}

func main() {
	ch := make(chan int)
	go producer(ch)
	for v := range ch {
		fmt.Println("Received ", v)
	}
}

Results of the:

7. Practice

Calculate the sum of squares and cubes of each digit in a number, and then add the sum of squares and the sum of cubes and print them.

package main

import (
	"fmt"
)

func digits(number int, dchnl chan int) {
	for number != 0 {
		digit := number % 10
		dchnl <- digit
		number /= 10
	}
	close(dchnl)
}
func calcSquares(number int, squareop chan int) {
	sum := 0
	dch := make(chan int)
	go digits(number, dch)
	for digit := range dch {
		sum += digit * digit
	}
	squareop <- sum
}

func calcCubes(number int, cubeop chan int) {
	sum := 0
	dch := make(chan int)
	go digits(number, dch)
	for digit := range dch {
		sum += digit * digit * digit
	}
	cubeop <- sum
}

func main() {
	number := 589
	sqrch := make(chan int)
	cubech := make(chan int)
	go calcSquares(number, sqrch)
	go calcCubes(number, cubech)
	squares, cubes := <-sqrch, <-cubech
	fmt.Println("Final output", squares+cubes)
}

Results of the:

Guess you like

Origin blog.csdn.net/www_dong/article/details/114242426