channels 是 goroutines之间通信的工具, 可以理解为管道, 虽然go也提供共享变量的方式, 但是更加推荐使用channel
func TestChan(t *testing.T) {
c := make(chan int)
go func() {
c <- 48
}()
fmt.Println(<- c)
// 保持持续运行
holdRun()
}
func holdRun() {
time.Sleep(1 * time.Hour)
}
<- 操作符用来接受和发送消息 chan <- 48 发送“48“ 进入管道, <-chan 接收消息
如果: c: = make(chan int, 10) 声明一个 传输整形 的buffer chan, 容量为10, 接收消息将可以立即返回除非channel里面没有消息, 发送者返回除非容量满
func TestDeadLock(t *testing.T) {
c := make(chan int)
c <- 42
val := <-c
fmt.Println(val)
}
func TestDeadLock1(t *testing.T) {
c := make(chan int)
//c := make(chan int, 0)
go func() {
c <- 48
}()
val := <-c
fmt.Println(val)
}
func TestDeadLock2(t *testing.T) {
c := make(chan int, 1)
c <- 42
val := <-c
fmt.Println(val)
}
对于方法, TestDeadLock 将:
fatal error: all goroutines are asleep - deadlock!
因为c <- 42 将会一直阻塞,直到出现消费者, 无容量的chan是同步, 正确的写法是 TestDeadLock1 这样不会死锁, 或者 TestDeadLock2 也不会死锁
func TestChan(t *testing.T) {
c := make(chan int, 10)
go func() {
c <- 48
c <- 96
time.Sleep(2 * time.Second)
c <- 200
}()
time.Sleep(1 * time.Second)
for v := range c {
fmt.Println(v)
}
// 保持持续运行
holdRun()
}
chan 可以配合 range 使用, 相当于每次foreach 每次去取一次
func TestDChan(t *testing.T) {
c := make(chan int)
go f1(c)
holdRun()
}
func f1(c chan <- int) {
c <- 0
<- c
}
f1的参数类型是 chan <- int 表明 这个chan单向的, 只能用来接收。 f1函数编译错误:
invalid operation: <-c (receive from send-only type chan<- int)
相对应的发送的chan : c <-chan string
select 关键字可以和 chan使用, 类似与switch
func TestSelect(t *testing.T) {
c1 := make(chan int)
c2 := make(chan int, 10)
c3 := make(chan int, 20)
go func(c1, c2, c3 chan<- int) {
for {
time.Sleep(1 * time.Second)
c1 <- 1
time.Sleep(1 * time.Second)
c1 <- 1
time.Sleep(1 * time.Second)
c1 <- 2
time.Sleep(1 * time.Second)
c1 <- 3
}
}(c1, c2, c3)
for {
select {
case int1 := <-c1:
fmt.Println("c1 value :", int1)
case int2 := <-c2:
fmt.Println("c2 value :", int2)
case int3 := <-c3:
fmt.Println("c3 vaule :", int3)
case <-time.After(2 * time.Second):
fmt.Println("timeount")
}
}
}
select 将阻塞直到有一个chan ready或者 超时,即 time.After
select {
case int1 := <-c1:
fmt.Println("c1 value :", int1)
case int2 := <-c2:
fmt.Println("c2 value :", int2)
case int3 := <-c3:
fmt.Println("c3 vaule :", int3)
default:
fmt.Println("nothing ready")
}
附 :
time.Afer 实现:
func After(d Duration) <-chan Time {
return NewTimer(d).C
}
func NewTimer(d Duration) *Timer {
c := make(chan Time, 1)
t := &Timer{
C: c,
r: runtimeTimer{
when: when(d),
f: sendTime,
arg: c,
},
}
startTimer(&t.r)
return t
}