Go Channel Goroutine

channel goroutine

Posted by Ricky on August 30, 2018

前言

写Golang也有一段时间了,一直写的都是一些数据处理,例如struct转json,json转map之类,几乎没有涉及到并发类的东西,但是高效简洁的并发才是Go语言的精髓所有,如果没有使用到 这个功能,那等于没有使用Go 今天就简单看下go语言里面的channel 和 goroutine

    package main
    
    import (
    	"fmt"
    	"strconv"
    	"sync"
    )
    
    func main() {
    	var group sync.WaitGroup
    	emps := 20
    	ch := make(chan string, emps)
    	ch1 := make(chan struct{})
    
    	//读取ch的数据,
    	go func() {
    		for v := range ch {
    
    			fmt.Println("pppppppppppp==========", v)
    		}
    		ch1 <- struct {}{} //执行完成之后,写入一个信号
    	}()
    
    
    
    	for e := 0; e < emps; e++ {
    		fmt.Println("for e", e)
    		group.Add(1)
    		go func() {
    			defer group.Done()
    			fmt.Println("go for e", e)
    			//time.Sleep(time.Duration(rand.Intn(200)) * time.Millisecond)
    			ch <- strconv.Itoa(e)
    		}()
    	}
    
    	group.Wait()
    	close(ch)
    
    	<-ch1 //主程序读取到信号之后 退出
    }

解读

上面这段代码,首先定义了一个叫做ch的有缓冲channel,有缓冲的通道里面最多只能存20个信号,如果没有被读取,那么将无法继续存入 主程序在开始的时候,就启动了一个goroutine读取ch的信号 下面的for循环,是开启了20个并发,每个并发都往ch通道里面传递了一个数据 主程序必须等待所有的并发都执行完成,所有有一个group的wait,每启动一个goroutine就add一个,同时,每一个goroutine执行完成,都需要 调用group.Done()来告知主程序我已经执行完成,最后要关闭这个ch通道 ch通道关闭之后,上面的for range 就不会在继续读取,但是,这里也是一个goroutine,通道关闭之后,自然不会继续循环,但是主程序并不知道这个goroutine的 任务何时才执行完成,所以需要等这个goroutine执行完成之后,再写一个通道ch1 主程序在接收到这个信号之后再退出