Golang中的Channel
goroutine和goroutine之间通过channel通信
channel的创建
1 使用make创建
channel创建可以用make方法,如:
c := make(chan int)
此外,如果make方法第二个参数多写一个数字,则表示对channel作buffer缓冲:
// 表示channel中每接收3个后再给接收者
c := make(chan int, 3)
2 使用var创建
不用make的话,也可以用var:
var c chan int // 此时c为nil
如果创建channel数组,则写法如下:
var channels [10]chan int
channel的传与收
往创建好的channel中传数据使用<-表示,如:
c <- 1
c <- 2
注意:往channel传数据后必须要有接收者,否则程序运行会报deadlock
较完整的示例片段如下:
// 创建一个channel
c := make(chan int)
// 起一个goroutine,用来接收channel中的数据并打印
go func() {
for {
n := <-c
fmt.Println(n)
}
}()
// 向channel中传数据
c <- 1
c <- 2
// 这里加个sleep,是为了避免channel中的数据还没打印,main函数就退出了
time.Sleep(time.Millisecond)
channel可作参数和返回值
channel可以作为参数传递,也可以作返回值。
需要注意的是,channel作为收数据还是发数据,写法是不一样的。
chan<- int 和<-chan int这两个是有区别的:
- chan<- int表示send only,只能往里发
- <-chan int表示revice only,只能从里收
channel的close
发送方可以使用close©方法来关闭channel,以告诉接收方没有新数据了。
channel关闭后,接收者还能接收数据不会报错,不过接收到的是对应类型的零值
如何判断channel是否关闭?
方法(1): 通过if判断
n, ok := <-c
if !ok {
fmt.Println("channel 没有数据了")
break
}
方法(2): 通过range
for n := range c {
...
}
使用sync.WaitGroup等待goroutine任务结束
之前使用time.Sleep(time.Millisecond)的方式来让main函数等待任务完成,但是不太好。
golang中提供了sync.WaitGroup方法来实现这个功能
例:
package main
import (
"fmt"
"sync"
)
func doWork(id int,
w worker) {
for n := range w.in {
fmt.Printf("Worker %d received %c\n",
id, n)
w.done()
}
}
type worker struct {
in chan int
done func()
}
func createWorker(
id int, wg *sync.WaitGroup) worker {
w := worker{
in: make(chan int),
done: func() {
wg.Done()
},
}
go doWork(id, w)
return w
}
func chanDemo() {
var wg sync.WaitGroup
var workers [10]worker
for i := 0; i < 10; i++ {
workers[i] = createWorker(i, &wg)
}
wg.Add(20)
for i, worker := range workers {
worker.in <- 'a' + i
}
for i, worker := range workers {
worker.in <- 'A' + i
}
wg.Wait()
}
func main() {
chanDemo()
}
select的使用
例:
var c1, c2 chan int
select {
case n := <-c1:
fmt.Println("received from c1:", n)
case n := <-c2:
fmt.Println("received from c2:", n)
default:
fmt.Println("no value received")
}
注意:通过var方式声明的c1和c2默认是nil,但用select方式并不会报错,因为有default兜底。
如果这里没有default,程序则会报deadlock,因为这里只有接收者,没有channel的发送者
还没有评论,来说两句吧...