[Basics of Go combat] What communication is used between processes

Hits: 0

Table of contents

1. Introduction

2. Data structure

Three, rookie combat

1. Create g009.go

2. Compile and run

3. Running results

1. Introduction

Channels are one of the most core functions in Go, so understanding the principles of channels is very important for learning and using Go. Channel is a way of communication between goroutines, which can be compared to the way of process pipeline [communication] in Unix . Channel is an important structure supporting the high-performance concurrent programming model of Go language.

A channel is like a conveyor belt or a [queue] , and always follows the First In First Out (First In First Out) rule to ensure the order of sending and receiving data. At any one time, only one goroutine can access the channel to send and get data.

2. [Data structure]

// channel data structure 
type hchan struct {
    qcount    uint            // The number of remaining elements in the current queue 
    dataqsiz uint            // The length of the ring queue, that is, the number of elements that can be stored 
    buf       unsafe .Pointer // The pointer of the ring queue 
    elemsize uint16          // The size of each element 
    closed uint32          // The sign is closed Status 
    elemtype *_type          // Element type 
    sendx     uint            // Queue subscript, indicating the location where the element is stored in the queue when it is written 
    recvx     uint            // Queue subscript, indicating that the element is read from this position in the queue 
    recvq waitq           // Waiting to read message goroutine queue 
    sendq waitq           // goroutine queue waiting to write messages 
    lock mutex               // mutex, chan does not allow concurrent read and write 
}

Three, rookie combat

Actual requirements:

Implement a function with a program, the prototype is: void printNumber(int N),
internally create three threads A, B, C, the three threads alternately output numbers between 1 and N, and thread A outputs 1,
4, 7…, B thread 2, 5, 8…, C thread output 3, 6, 9…,

Schedule now!

1. Create g009.go

/*
 * @Author: rookie combat
 * @FilePath: /go110/go-009/g009.go
 * @Description: channel
 */

package main

import (
    "fmt"
    "runtime"
    "sync/atomic"
)

var index int32
 var maxNum int32

// Open the three channels of ABC for three channels to monitor data respectively 
var chA = make(chan int32)
 var chB = make(chan
 int32) var chC = make (chan int32)

// monitor close 
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 ) {
     //Open three coroutines to do tasks 
    go printA ( N )
    go printB(N)
    go printC(N)

    //Send data to chA to notify it to start printing
    chA <- 1

    //wait
    <-chClose

    close(chA)
    close(chB)
    close(chC)
    close(chClose)

    fmt.Println("done")
}

func printA ( N int ) {
     //Start listening 
    for {
         select {
         case v := <-chA:
            atomic.AddInt32(&index, 1)
            fmt.Print(v)
            fmt.Print("A,")
            chB <- v + 1  // notify B to start printing 
            if v == maxNum {
                chClose <- 1
                return
            }
        case <-chClose:
            return
        }
    }

}

func printB ( N int ) {
     //B starts listening 
    for {
         select {
         case v := <-chB:
            atomic.AddInt32(&index, 1)
            fmt.Print(v)
            fmt.Print("B,")
            chC <- v + 1  // tell C to start printing

            if v == maxNum {
                chClose <- 1
                return
            }
        case <-chClose:
            return
        }
    }
}

func printC ( N int ) {
     //Start listening 
    for {
         select {
         case v := <-chC:
            atomic.AddInt32(&index, 1)
            fmt.Print(v)
            fmt.Print("C,")
            chA <- v + 1  // notify A via channel 
            if v == maxNum {
                chClose <- 1
                return
            }
        case <-chClose:
            return
        }
    }
}

func main() {
     // use the built-in function to print 
    println( "Hello" , "Rookie combat" )

    index = 0
    maxNum = 20
    printNumber(20)

    // current version 
    fmt.Printf( "Version: %s \n" , runtime.Version())
}

2. Compile and run

1. Generate module dependencies

go mod init g009

2. Compile

go build g009.go 

3. Compiled directory structure

└── go-009
    ├── g009
    ├── g009.go
    └── go.mod

4. Run

go run g009

3. Running results

Hello rookie combat
1A, 2B, 3C, 4A, 5B, 6C, 7A, 8B, 9C, 10A, 11B, 12C, 13A, 14B, 15C, 16A, 17B, 18C, 19A, 20B, done
21C, version: go1. 17.10 

Be a rookie, keep learning!

You may also like...

Leave a Reply

Your email address will not be published.