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: