> 文档中心 > 【Go实战基础】进程之间是使用什么通信的

【Go实战基础】进程之间是使用什么通信的

目录

一、简介

二、数据结构

三、菜鸟实战

1、创建 g009.go

2、编译和运行

3、运行结果

一、简介

channel 是 Go中最核心的功能之一,因此理解 channel 的原理对于学习和使用 Go 非常重要。 channel 是 goroutine 之间通信的一种方式,可以类比成 Unix 中进程管道通信方式,channel 是支撑 Go 语言高性能并发编程模型的重要结构。

通道像一个传送带或者队列,总是遵循先进先出(First In First Out)的规则,保证收发数据的顺序。在任何时候,同时只能有一个 goroutine 访问通道进行发送和获取数据。

二、数据结构

// channel 数据结构type hchan struct {    qcount   uint    // 当前队列中剩余元素个数    dataqsiz uint    // 环形队列长度,即可以存放的元素个数    buf      unsafe.Pointer // 环形队列指针    elemsize uint16  // 每个元素的大小    closed   uint32  // 标识关闭状态    elemtype *_type  // 元素类型    sendx    uint    // 队列下标,指示元素写入时存放到队列中的位置    recvx    uint    // 队列下标,指示元素从队列的该位置读出    recvq    waitq   // 等待读消息的 goroutine 队列    sendq    waitq   // 等待写消息的 goroutine 队列    lock mutex// 互斥锁,chan 不允许并发读写}

三、菜鸟实战

实战需求:

用程序实现一个函数,原型为:void printNumber(int N),
内部创建三个线程 A、B、C,三个线程交替输出 1 到 N 之间的数字,
A 线程输出 1、4、7…,B 线程 2、5、8…,C 线程输出 3、6、9…,

马上安排!

1、创建 g009.go

/* * @Author: 菜鸟实战 * @FilePath: /go110/go-009/g009.go * @Description: channel */package mainimport ("fmt""runtime""sync/atomic")var index int32var maxNum int32// 开 ABC 三个channel 分别用于三个 channel 监听数据var chA = make(chan int32)var chB = make(chan int32)var chC = make(chan int32)// 监听关闭var chClose = make(chan int32)type Values struct {m map[string]string}func (v Values) Get(key string) string {return v.m[key]}func printNumber(N int) {//开三个协程做任务go printA(N)go printB(N)go printC(N)//给chA发数据通知它开始打印chA <- 1//等待<-chCloseclose(chA)close(chB)close(chC)close(chClose)fmt.Println("done")}func printA(N int) {//开始监听for {select {case v := <-chA:atomic.AddInt32(&index, 1)fmt.Print(v)fmt.Print("A,")chB <- v + 1 //通知B开始打印if v == maxNum {chClose <- 1return}case <-chClose:return}}}func printB(N int) {//B开始监听for {select {case v := <-chB:atomic.AddInt32(&index, 1)fmt.Print(v)fmt.Print("B,")chC <- v + 1 // 通知C开始打印if v == maxNum {chClose <- 1return}case <-chClose:return}}}func printC(N int) {//开始监听for {select {case v := <-chC:atomic.AddInt32(&index, 1)fmt.Print(v)fmt.Print("C,")chA <- v + 1 // 通过 channel 通知 Aif v == maxNum {chClose <- 1return}case <-chClose:return}}}func main() {// 使用内置函数打印println("Hello", "菜鸟实战")index = 0maxNum = 20printNumber(20)// 当前版本fmt.Printf("版本: %s \n", runtime.Version())}

2、编译和运行

# 1、生成模块依赖
go mod init g009
 
# 2、编译
go build g009.go 
 
# 3、编译后的目录结构
 
└── go-009
    ├── g009
    ├── g009.go
    └── go.mod
 
# 4、运行
go run g009

3、运行结果

Hello 菜鸟实战
1A,2B,3C,4A,5B,6C,7A,8B,9C,10A,11B,12C,13A,14B,15C,16A,17B,18C,19A,20B,done
21C,版本: go1.17.10 

  菜鸟实战,持续学习!