在学习go语言channel中,读到最多的一句话便是通过通信共享内存,而不是通过共享内存来进行通信(Do not communicate by sharing memory;instead,share memory by communicating.)那么如何来理解这句话呢?个人理解通过共享内存来通信的话必须保证数据的安全及正确性,即需要通过加锁等手段进行控制,但是此种方式带来的性能开销以及可能造成的死锁问题处理起来较为繁琐。而go语言则通过channel来通信,通过通信来传递内存数据,个人认为更加优雅简洁与高效。 很多情况下我们需要主动关闭goroutine,那么如何实现呢?
funcproducer(out chan<- int, exit chanstruct{}) { for i := 0; i < 10; i++ { data := i * i fmt.Println("生产者生产数据:", data) out <- data } exit <- struct{}{} }
funcconsumer(in <-chanint, exit chanstruct{}) { for { select { case <-exit: fmt.Println("收到退出信号") // 不建议使用goto语句 return// 必须return, 否则goroutine不会结束 case data := <-in: fmt.Println("消费者得到数据:", data) } } }
funcproducer(out1, out2 chan<- int) { for i := 0; i < 10; i++ { data := i * i fmt.Println("生产者生产数据:", data) out1 <- data time.Sleep(1 * time.Second) out2 <- data * 2 } close(out1) close(out2) }
funcconsumer(in1, in2 <-chanint) { for { select { case data, ok := <-in1: if !ok { fmt.Println("收到ch1关闭信号") in1 = nil } fmt.Println("消费者得到数据:", data) case data, ok := <-in2: if !ok { fmt.Println("收到ch2关闭信号") in2 = nil } fmt.Println("消费者得到数据:", data) } if in1 == nil && in2 == nil { return } } }
funcproducer(out chan<- int, ctx context.Context, cancel context.CancelFunc) { for i := 0; i < 10; i++ { data := i * i fmt.Println("生产者生产数据:", data) out <- data } subCtx, _ := context.WithCancel(ctx) go consumer2(subCtx) cancel() }
funcconsumer(in <-chanint, ctx context.Context) { for { select { case data := <-in: fmt.Println("消费者得到数据:", data) case <-ctx.Done(): fmt.Println("收到结束信号") return// 必须return, 防止goroutine泄露 } } }
funcconsumer2(ctx context.Context) { for { select { case <-ctx.Done(): fmt.Println("收到结束信号, consumer2") return// 必须return, 防止goroutine泄露 } } }