在 Go 语言中,通道(Channel)是一种用于在 goroutine 之间进行通信和同步的机制。通道提供了一种安全、简单、高效的方式来共享数据,避免了显式的锁和条件变量。
1、单向channel
package main
import (
"fmt"
"time"
)
func main() {
//默认情况下,channel是双向的
/*
var ch1 chan int //双向channel
var ch2 chan<- int // 单向channel,只能写入int数据
var ch3 <-chan int // 单向的,只能读取
*/
c := make(chan int)
//var send chan<- int = c //send-only
//var read <-chan int = c //write-only
//send <- 1
//<-read
go producer(c)
go consumer(c)
time.Sleep(time.Second * 10)
}
func producer(out chan<- int) {
for i := 0; i < 10; i++ {
out <- i
}
close(out)
}
func consumer(in <-chan int) {
for num := range in {
fmt.Println(num)
}
}
2 、通过channel实现交叉打印
打印:12a34b56c78d910e1112f1314g1516h1718i1920j2122k2324
package main
import (
"fmt"
"time"
)
var number, letter = make(chan bool), make(chan bool)
func main() {
go printNum()
go printLetter()
number <- true
time.Sleep(time.Second * 10)
}
func printNum() {
i := 1
for {
<-number
fmt.Printf("%d%d", i, i+1)
i += 2
letter <- true
}
}
func printLetter() {
i := 0
s := "abcdefghijk"
for {
<-letter
if i >= len(s) {
return
}
fmt.Printf(string(s[i : i+1]))
i += 1
number <- true
}
}
3、select作用多个channel
package main
import (
"fmt"
"time"
)
var done = make(chan struct{})
func main() {
//select 类似于 switch case 语句
g1Channel := make(chan struct{})
g2Channel := make(chan struct{})
go g1(g1Channel)
go g2(g2Channel)
// 我们要监控多个channel,任何一个channel返回都知道
// 某一个分子就绪了就执行该分支
timer := time.NewTimer(time.Second * 2)
for {
select {
case <-g1Channel:
fmt.Println("g1 done")
case <-g2Channel:
fmt.Println("g2 done")
case <-timer.C:
fmt.Println("timeout")
return
}
}
time.Sleep(time.Second * 10)
}
func g1(ch chan struct{}) {
time.Sleep(time.Second)
ch <- struct{}{}
}
func g2(ch chan struct{}) {
time.Sleep(time.Second * 3)
ch <- struct{}{}
}