主要问题1:
通道各种情况如图所示
针对以下情况:
x , ok := ch
if !ok {
break
}
通道channel 当且仅当关闭后(close),同时通道里面的值被取完才能返回 ‘ok = false’
执行并分析以下例子:
package main
import (
"fmt"
"math/rand"
"time"
)
func sendNum(ch chan int) {
for {
x := rand.Intn(10)
ch <- x
time.Sleep(time.Second * 3)
}
}
func main() {
ch := make(chan int, 1)
go sendNum(ch)
for {
x, ok := <-ch
if !ok {
break
}
fmt.Println(x, ok)
time.Sleep(time.Second)
}
}
for ret := range ch2 {
fmt.Println(ret)
}
for ret := range ch2
实则是从channel
中取出数字并逐个打印的结果
要注意的是需要close(ch2)
才能正常使用,否则就会deadlock
执行并分析以下例子:
package main
import (
"fmt"
"sync"
"time"
)
// 1. 生成100个数 放进 ch1
// 2. 从 ch1 中取数 平方后放进 ch2
// 3. 从 ch2 中打印
var wg sync.WaitGroup
var once sync.Once
func f1(ch1 chan<- int) {
defer wg.Done()
for i := 0; i < 100; i++ {
ch1 <- i
}
close(ch1)
}
func f2(ch1 <-chan int, ch2 chan<- int) {
defer wg.Done()
for {
i, ok := <-ch1
if !ok {
break
}
ch2 <- i * i
}
once.Do(func() { close(ch2) })
}
func main() {
ch1 := make(chan int, 100)
ch2 := make(chan int, 100)
wg.Add(3)
go f1(ch1)
go f2(ch1, ch2)
go f2(ch1, ch2)
// range 的使用范围特殊在于 ch2 关闭即可 跳出循环
// 同时 range 遍历时会把通道中的数字取出
for ret := range ch2 {
fmt.Println(ret)
}
for i := 0; i < 5; i++ {
time.Sleep(time.Second)
t := <-ch2
fmt.Println(t)
}
}