brief introduction

go

To configure

GOMAXPROCS Set logic CPU Number , In general use CPU Core quantity value . Use enough threads to improve golang Parallel execution efficiency . If your business is IO For dense type, you can set multiple times and CPU For better performance . If Go If the program is executed in the container, the value should be reduced according to the situation , Because the container cannot use all the cores of the host . Setting a smaller value can avoid the overhead of thread switching .

Use channel Carry out process communication

Define the channel

ch1 := make(chan string) // Defines an unbuffered string passageway
ch2 := make(chan string , 4) // Defined a 4 An element of string passageway 

Channel operator

ch1 <- "Chengdu" // Write data to channel
itemOfCh1 := <- ch1 // from ch1 The channel reads a piece of data
<- ch1 // Read the next value of the channel
var in_only chan<- int // Only receive channels
var out_only <-chan int // Read only the channel
close(ch) // Close channel 

The channel is blocked

By default, channels are synchronized unbuffered , The sender is blocked before the receiver is ready . If there is no data in the channel, the receiver is blocked .

package main
import (
"fmt"
"time"
)
func f1(in chan int) {
data := <-in
fmt.Println(data)
}
func main() {
out := make(chan int)
out <- 2
fmt.Println(v)
go f1(out)
time.Sleep(100 * time.Millisecond)
}
 modify out:=make(chan int , 1)

Use semaphores

The semaphore can be used to make the main process wait for the completion of the sub process to exit the execution .

package main
import (
"fmt"
"time"
)
func f1(in chan int, done chan int) {
data := <-in
fmt.Println(data)
time.Sleep(10e9)
done <- 1
}
func main() {
out := make(chan int)
done := make(chan int)
go f1(out, done)
out <- 2
<-done
}

Output 2 after 10 Seconds before the program exits , We don't need to use it sleep To let the main process execute .

Close channel

Explicitly close the channel , Closing the channel means that the sender will not send new data to the receiver . Only the sender needs to close the channel .

ch := make(chan int )
defer close(ch)
data,ok := <-ch // When data is received ok by true, Use ok It can detect whether the channel is closed or blocked

This is the case , The read channel will not report a deadlock error in the main process , Because after the channel is checked to be closed, the channel reading will not be carried out and the loop will jump out , Therefore, the channel that is not written will not be read . So there is no deadlock .

package main
import "fmt"
func makeStream(n int) chan bool {
ch := make(chan bool, n)
go func() {
for i := 0; i < n; i++ {
ch <- true
}
close(ch)
}()
return ch
}
func main() {
stream := makeStream(5)
for {
v, ok := <-stream
if !ok {
break
}
fmt.Println(v)
}
}

Use select Switch coroutines

selectfor
default
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
for i := 0; i < 10; i++ {
ch1 <- fmt.Sprintf("A%d", i)
}
}()
go func() {
for i := 0; i < 10; i++ {
ch2 <- fmt.Sprintf("B%d", i)
}
}()
go func() {
for {
select {
case v := <-ch1:
fmt.Println(v)
case v := <-ch2:
fmt.Println(v)
}
}
}()
time.Sleep(1e9)
}

You can use this pattern as a server to cycle through client requests

timer (Ticker)

type Ticker struct {
C <-chan Time // The channel on which the ticks are delivered.
r runtimeTimer
}

Timer C The variable will be based on the timer time you created , Write time to the channel within a given time

package main
import (
"fmt"
"time"
)
func main() {
t := time.NewTicker(time.Second)
go func() {
for {
v := <-t.C
fmt.Println(v)
}
}()
time.Sleep(10e9) // <-time.After(10e9) Use channels to set timeouts
}
time.Tick(duration)time.NewTicker(1e9).Ctime.After(duration)

Recovery of the process

panic
package main
import (
"log"
"time"
)
func doWork() {
time.Sleep(4e9)
panic("fk")
}
func main() {
go func() {
for {
log.Printf("another worker")
time.Sleep(1e9)
}
}()
go func() {
defer func() {
if err := recover(); err != nil {
log.Printf(" Something is wrong. %s", err)
}
}()
doWork()
}()
time.Sleep(10e9)
}

Use lock or channel

In one scene , There are multiple missions , One worker Deal with a task . This scenario is suitable for using channels and coroutines to solve problems

package main
type Task struct{}
type Result struct{}
func process(Task *Task) Result {
return Result{}
}
func main() {
tasks, results := make(chan Task), make(chan Result)
workCount := 10
// Create tasks
go func() {
for i := 0; i < workCount; i++ {
tasks <- Task{}
}
}()
// start-up worker
for i := 0; i < workCount; i++ {
go func() {
for {
t := <-tasks
result := process(&t) // Processing data
results <- result // Write structure
}
}()
}
// The result of consumption
}
  • The use of locks :

    • Accessing cached information in shared data structures
    • Save application context and state information data
  • The scenario of using channels :

    • Interact with the results of an asynchronous operation
    • Distribute tasks
    • Transfer data ownership