当学完了go的routines和channels之后,突发奇想,自己找了个应用场景去应用,但是遇到了问题
使用场景:分批处理数据,查找偶数,集合结果
/**
* 判断是否是偶数,存储在chan类型参数中
*/
func isEvenNum(result chan<- int, nums ...int) {
for _, k := range nums {
if k%2 == 0 {
result <- k
}
}
}
func ChannelUsCase() {
var c = make(chan int)
/**
定义三组需要处理的数据
*/
nums1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
nums2 := []int{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
nums3 := []int{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}
/**
异步开始任务
*/
go isEvenNum(c, nums1...)
go isEvenNum(c, nums2...)
go isEvenNum(c, nums3...)
/**
输出打印结果
*/
result := []int{}
for {
select {
case t := <-c:
fmt.Println(t)
result = append(result, t)
default:
break
}
}
fmt.Println(result)
}
我学习的结论是,select应该是当chan没有阻塞传参的时候,会走default结束,然后打印result的,可是结果只能走case中的打印,下面的fmt.Println(result) 由于阻塞一直未打印,求解
更多评论
那是因为在channel中的select使用break只会跳出select,不会作用到for上边去,而你又用了死循环,所以最后的打印语句永远执行不到。你可以在isEvenNum函数中多加一个判断执行完毕的标记channel。一种粗暴的做法如下:
var d = make(chan struct{})
var count int
go isEvenNum(c, d, nums1...)
go isEvenNum(c, d, nums2...)
go isEvenNum(c, d, nums3...)
result := []int{}
A:
for {
select {
case t := <-c:
fmt.Println(t)
result = append(result, t)
case <-d:
count++
if count == 3 {
break A
}
default:
break
}
}
fmt.Println(result)
}
#1