One, use two sync.WaitGroup and close the channel to achieve
package main
import("fmt""sync")funcmain(){
kk :=make(chanint,1000)var setwg sync.WaitGroup
var readwg sync.WaitGroup
for i :=1; i <3; i++{
setwg.Add(1)goSet(kk,&setwg)}for i :=1; i <3; i++{
readwg.Add(1)goRead(kk,&readwg)}
setwg.Wait()close(kk)//只要一个 chan 还有未读的数据,即使把它 close 掉,// 你还是可以继续把这些未读的数据消费完,而且bool值为true,之后才是读取零值数据和false
readwg.Wait()//或者下面的实现也可以//for {
// if len(kk) == 0 {
// close(kk)// readwg.Wait()// break// }//}}funcSet(kk chanint, wg *sync.WaitGroup){
defer wg.Done()for i :=1; i <3; i++{
kk <- i
}}funcRead(kk chanint,wg *sync.WaitGroup){
defer wg.Done()for{
i, ok :=<-kk
if!ok{
fmt.Println("ok:",ok)break}
fmt.Println(ok)
fmt.Println(i)}}
Second, use two sync.WaitGroup and the cancel operation through context to achieve
package main
import("context""fmt""sync")funcmain(){
kk :=make(chanint,1000)
ctx, cancel := context.WithCancel(context.Background())var setwg sync.WaitGroup
var readwg sync.WaitGroup
for i :=1; i <3; i++{
setwg.Add(1)goSet(kk,&setwg)}for i :=1; i <3; i++{
readwg.Add(1)goRead(kk, ctx,&readwg)}
setwg.Wait()for{
iflen(kk)==0{
cancel()
readwg.Wait()break}}}funcSet(kk chanint, wg *sync.WaitGroup){
defer wg.Done()for i :=1; i <3; i++{
kk <- i
}}funcRead(kk chanint, ctx context.Context,wg *sync.WaitGroup){
defer wg.Done()for{
select{
case<-ctx.Done():returndefault:iflen(kk)>0{
i:=<-kk
fmt.Println(i)}}}}
Third, use a sync.WaitGroup and the cancel operation through the context to determine the number of goruntines (not significant)
package main
import("context""fmt""runtime""sync")funcmain(){
kk :=make(chanint,1000)
ctx, cancel := context.WithCancel(context.Background())var setwg sync.WaitGroup
for i :=1; i <3; i++{
setwg.Add(1)goSet(kk,&setwg)}for i :=1; i <3; i++{
goRead(kk, ctx)}
setwg.Wait()for{
iflen(kk)==0{
cancel()break}}for{
fmt.Println("runtime.NumGoroutine()",runtime.NumGoroutine())if runtime.NumGoroutine()==1{
break}}}funcSet(kk chanint, wg *sync.WaitGroup){
defer wg.Done()for i :=1; i <3; i++{
kk <- i
}}funcRead(kk chanint, ctx context.Context){
for{
select{
case<-ctx.Done():returndefault:iflen(kk)>0{
i:=<-kk
fmt.Println(i)}}}}