go语言进阶和依赖管理| 豆包MarsCode AI 刷题

88 阅读3分钟

go语言进阶

1.并发与并行

image.png

go可以充分发挥多核优势,高效运行

1-1 goroutine

goroutine 是 Go 语言中的并发执行单元。它由 Go 运行时调度器管理,不依赖于操作系统线程的直接调度。每个 goroutine 都是由 Go 运行时管理的,它们是独立的执行流,在同一线程或多个线程上运行。

线程与协程

image.png

一个异步例子

package main

import "fmt"

func sayHello() {
    fmt.Println("Hello from Goroutine!")
}

func main() {
    for a := 0; a < 10; a++ {
        go sayHello() // 创建并启动一个 goroutine
}

    fmt.Println("Hello from Main!")
}

要创建一个 goroutine,只需要使用 go 关键字,后面跟上一个函数调用。这样,Go 运行时会异步地执行这个函数,而不会阻塞当前的执行流程。

在上面的代码中,go sayHello() 会启动一个新的 goroutine 执行 sayHello 函数,而 main 函数中的 fmt.Println 会立即执行。所以for里面十次并行的函数还没运行完,main函数就结束了,sayhello函数没有被运行10次。如果去掉前面的go,则程序一步一步运行sayhello函数成功运行十次。通过通信共享内存

1-3Channel

首先明白有缓冲通道和无缓冲通道

无缓冲通道,也称为同步通道,在传输数据时,发送方和接收方必须在同一时刻进行配对操作,才能成功地进行数据传输。换句话说,数据只有在有接收者准备好接收时,发送者才能将数据发送出去,反之亦然。

缓冲通道在其内部有一个缓冲区,可以存储一定数量的数据。在发送数据时,发送方不需要等待接收方立即接收数据,只要缓冲区没有满,发送操作就会立即成功。而接收方则可以在稍后的时间内从通道中取出数据。如果缓冲区为空,接收方就会阻塞直到有数据可用

区别 image.png 无缓冲通道make(chan int)

   ch := make(chan int) // 创建无缓冲通道 
   // 发送数据 
   go func() { 
   ch <- 42    // 发送数据到通道,发送会阻塞,直到有接收者准备好 
   }() 
    
    // 接收数据 
    val := <-ch // 接收数据,这也会阻塞,直到有发送者发送数据 
    fmt.Println(val) // 输出:42

有缓冲通道make(chan int, 2)

ch := make(chan int, 2) // 创建一个缓冲区大小为2的通道 
// 发送数据 
ch <- 1    // 不会阻塞 
ch <- 2    // 不会阻塞 
// 当缓冲区已满时,以下发送操作会被阻塞  
ch <- 3    // 会阻塞,直到接收者消费数据 
// 接收数据 
val := <-ch      // 从缓冲区接收数据 
fmt.Println(val) // 输出:1

1-4并发安全Lock

锁的目的是防止多个线程(或进程)同时访问共享资源(如内存、文件、数据库等),导致数据不一致。通过锁,程序可以确保某个共享资源在同一时刻只有一个线程能够访问,其他线程则需要等待。

1-5waitgroup

有多个并发任务(比如多个 HTTP 请求),并希望在所有任务完成后进行某些操作, 由于不知道多线程要运行多久,所以使用 WaitGroup 来等待所有并发任务完成