引言
最近在学习go语言中遇到一个爬虫项目的教学,其中有在schduler中使用双层chan的应用场景。并不太明白为甚要嵌套形成chan chan的结构,最近从网上找了点资料才明白是为了避免出现后进先出(LIFO)的情况,对协程起到了很好的管理实现先进先出(FIFO)的要求。
双chan示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| > util.go package util
import ( "sync" )
func DoubleChan(cc chan chan string, str string, wg *sync.WaitGroup) { //创建一个chan c := make(chan string) //用于阻塞住双层chan中的一个chan cc <- c wg.Add(1) go func(str string) { //把值传入到被阻塞住的chan里 c <- str time.Sleep(time.Microsecond * 100) wg.Done() }(str)
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| > main.go package main
import ( "fmt" "strconv" "sync"
"1234.com/test/util" )
func main() { wg := sync.WaitGroup{} //创建一个双层chan cc := make(chan chan string, 5000) go getstr(cc) for i := 0; i < 1000; i++ { str := `Number:` + strconv.Itoa(i) util.DoubleChan(cc, str, &wg) } wg.Wait() }
func getstr(getstr chan chan string) { for { //从双层chan中取一个chan出来 c := <-getstr //再从chan里面取值出来 r := <-c fmt.Println(r) } }
|
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $>go run mian.go Number:0 Number:1 Number:2 Number:3 Number:4 Number:5 Number:6 Number:7 Number:8 . . . Number:999
|
单chan示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| util.go package util
import ( "sync" )
func SingleChan(cc chan string, str string, wg *sync.WaitGroup) { wg.Add(1) go func(str string) { cc <- str // time.Sleep(time.Microsecond * 100) wg.Done() }(str)
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| main.go package main
import ( "fmt" "strconv" "sync"
"1234.co/test/util" )
func main() { wg := sync.WaitGroup{} sc := make(chan string, 5000) go getstr1(sc) for i := 0; i < 1000; i++ { str := `Number:` + strconv.Itoa(i) util.SingleChan(sc, str, &wg) } wg.Wait() } func getstr1(ch chan string) { for { c := <-ch fmt.Println(c) } }
|
输出结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| go run mian.go Number:1 Number:0 Number:2 Number:7 Number:3 Number:4 Number:5 Number:6 Number:13 Number:12 Number:11 Number:8 Number:9 Number:10 . . . Number:185 Number:188 Number:189
|
结论
双通道会利用通道阻塞的原理将无序的内通道,按照用户意愿的顺序压入外通道,从外通道取的值既是用户意愿的顺序。