goroute and channel in Go

Basic knowledge

Processes and threads

  • process
    Process is an execution process of a program in the operating system, which is an independent unit of resource allocation and scheduling.
  • thread
    Thread is an execution entity of a process and the basic unit of CPU scheduling and allocation. It is a smaller basic unit that can run independently than a process.
  • Association
    Lightweight threads
    - Links
    A process can create and revoke multiple threads, and multiple threads in the same process can execute concurrently.

Concurrent and parallel

  • Concurrency: multithreaded programs run on a core CPU
  • Parallel: multithreaded programs run on multiple core CPU s

goroute

goroute scheduling model

	M: Threads of the operating system
	P: Context
	G: goroute, orchestration
  • Relationship:

      One P can only execute one goroute, and the rest are waiting
    

  • Communication between goroute s:

      1. Global variables and lock synchronization
      2,channel
    

channel

  • Initialization
	var a chan int
	a = make(chan int, 10)
  • Read / write data
	// Writing pipeline
	var b int
	a <- b

	// Readout pipeline
	b = <- a
  • Definition of read / write pipes

      Read only var ch < - Chan int
      Write var ch Chan < - int only
    
  • Close channel

package main

import(
	"fmt"
)

func testChan() {
	var a chan int
	a = make(chan int, 10)

	for i := 0; i < 10; i++ {
		a <- i
	}

	// Close the pipeline
	close(a)

	for {
		var b int
		b,ok:=<-a
		if ok== false{
			fmt.Println("Chan Closed")
			break	
		}

		fmt.Println(b)
	}

}

func main() {
	testChan()
}

  • Example of pipe closure

      If the pipeline is not closed, forrnage will wait
      After the pipeline is closed, forrange exits
      Check whether the pipeline is closed v, ok: = < Ch
    
package main

import (
	"fmt"
)

func calc(taskChan chan int, resChan chan int,
	exitChan chan bool) {
	for v := range taskChan {
		flag := true
		for i := 2; i < v; i++ {
			if v%i == 0 {
				flag = false
				break
			}
		}

		if flag {
			resChan <- v
		}
	}

	fmt.Println("exit")
	exitChan <- true
}

func main() {
	intChan := make(chan int, 1000)
	resultChan := make(chan int, 1000)
	exitChan := make(chan bool, 8)

	go func() {
		for i := 0; i < 10000; i++ {
			intChan <- i
		}

		close(intChan)
	}()

	for i := 0; i < 8; i++ {
		go calc(intChan, resultChan, exitChan)
	}

	//Wait for all calculated goroutine s to exit
	go func() {
		for i := 0; i < 8; i++ {
			<-exitChan
			fmt.Println("wait goroute ", i, " exited")
		}
		close(resultChan)
	}()

	for v := range resultChan {
		fmt.Println(v)
	}
}
  • channel synchronization example

      A coroutine writes to the pipeline, closes the pipeline after writing, and throws something to the marked pipeline
      A process reads data from the pipeline and throws a thing to the marked pipeline after reading it
      The main thread reads from the tag pipeline to wait
    
package main

import (
	"fmt"
)

func read(ch chan int, exitCh chan struct{}) {
	for i := 0; i < 10; i++ {
		ch <- i
	}

	close(ch)
	var a struct{}
	exitCh <- a
}

func write(ch chan int, exitCh chan struct{}) {
	for {
		a, ok := <-ch
		if !ok {
			break
		}
		fmt.Println(a)
	}

	var a struct{}
	exitCh <- a
}

func main() {
	ch := make(chan int, 10)
	exitCH := make(chan struct{}, 2)

	go read(ch, exitCH)
	go write(ch, exitCH)

	var total = 0
	for _ = range exitCH {
		total++
		if total == 2 {
			break
		}
	}
}

Output:
0
1
2
3
4
5
6
7
8
9

  • select use
package main

import (
	"fmt"
	"time"
)

func write(ch1 chan int, ch2 chan int) {
	for i := 0; i < 10; i++ {
		ch1 <- i
		time.Sleep(time.Second)
		ch2 <- i * 2
		time.Sleep(time.Second)
	}
}

func main() {
	ch1 := make(chan int, 10)
	ch2 := make(chan int, 10)

	go write(ch1,ch2)

	for {
		select {
		case v := <-ch1:
			fmt.Println(v)
		case v := <-ch2:
			fmt.Println(v)
		default:
			fmt.Println("get data timeout")
			time.Sleep(time.Second)
		}
	}
}

  • recover in cooperation

      To prevent the panic in the cooperation process from causing the main thread to hang up and capture the panic in the cooperation process
    
package main

import (
	"fmt"
	"time"
)

func write() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("catch err")
		}
	}()

	var m map[string]int
	m["123"] = 1

}

func main() {
	go write()

	time.Sleep(time.Second)
}

Output:
catch err

32 original articles published, 14 praised, 4135 visited
Private letter follow

Tags: REST

Posted on Thu, 06 Feb 2020 08:27:49 -0500 by gonsman