生成器的两种写法
package main
import (
"fmt"
"time"
)
// 1. 当不确定参数有几个channel的时候,采用这个写法
func fanIn(c1, c2 chan string) chan string {
c := make(chan string)
go func() {
for {
c <- <-c1
}
}()
go func() {
c <- <-c2
}()
return c
}
// 2. 当知道参数的数量, 只开一个go rountine即可
func fanInBySelect(c1, c2 chan string) chan string {
c := make(chan string)
go func() {
for {
select {
case m := <-c1:
c <- m
case m := <-c2:
c <- m
}
}
}()
return c
}
func msgGen(name string) chan string {
m := make(chan string)
go func() {
i := 0
for {
time.Sleep(time.Second * 2)
m <- fmt.Sprintf("service %s message %v", name, i)
i++
}
}()
return m
}
func main() {
c1 := msgGen("service1")
c2 := msgGen("service2")
// c1, c2 谁先来到,谁先写到C里面,先处理谁
c := fanIn2(c1, c2)
for {
fmt.Println(<-c)
}
}
未知参数数量时候的写法
变量作用域的问题
func fanIn2(chs ...chan string) chan string {
c := make(chan string)
// chan 在go func外部,只有一份,chan2 会把chan1覆盖掉,因此结果所有的go rountine都用这一份chan2
for _, ch := range chs {
go func() {
for {
c <- <-ch
}
}()
}
return c
}
新写一个变量,保存一下ch的值
func fanIn2(chs ...chan string) chan string {
c := make(chan string)
// chan 在go func外部,只有一份,chan2 会把chan1覆盖掉,因此结果所有的go rountine都用这一份chan2
// chCopy作用域在他头顶上的花括号,花括号进来两次,chCopy会有两份
for _, ch := range chs {
chCopy := ch
go func() {
for {
c <- <-chCopy
}
}()
}
return c
}
函数传参, 与上面道理一致
func fanIn2(chs …chan string) chan string {
c := make(chan string)
// chan 在go func外部,只有一份,chan2 会把chan1覆盖掉,因此结果所有的go rountine都用这一份chan2
for _, ch := range chs {
go func(in chan string) {
for {
c <- <-in
}
}(ch)
}
return c
}