santisify Site

Back

Go并发编程Blur image

并发模型(CSP理论、Goroutine轻量级线程)#

基础概念#

并发: 多个任务在同一时间段内交替执行, 但不一定同时执行, 也就是任务之间的切换是有序的, 任务之间是有依赖关系的.

并行: 多个任务在同一时刻同时执行

CSP理论:

  • 核心思想: 不要通过共享内存来通信,而要通过通信来共享内存
  • 组成要素: Process (进程\协程)、Channel (通道)

应用场景#

Goroutine

  • 高并发Web服务器:每个请求一个Goroutine
  • 数据处理流水线:多个处理阶段并行执行
  • 实时消息推送:WebSocket连接管理
  • 定时任务调度:后台定时执行任务
  • 并发爬虫:同时抓取多个网页

传统多线程与Goroutine的区别

特性传统线程Goroutine
创建成本1-2MB2KB
创建速度
调度方式操作系统调度Go运行时调度
上下文切换完整线程切换用户态轻量切换

通道(Channel)#

Channel是Go语言中各个并发执行体间的通信机制,是类型相关的管道,用于在goroutine之间传递数据和同步执行。

不要通过共享内存来通信,而应通过通信来共享内存

// 创建channel
ch1 := make(chan int)        // 无缓冲channel 
ch2 := make(chan int, 10)   // 有缓冲channel,容量10

// 操作
ch1 <- 42    // 发送数据到channel
value := <-ch1 // 从channel接收数据
close(ch1)   // 关闭channel

// 特殊用法
value, ok := <-ch1 // 检查channel是否关闭
go

缓冲区区别

  • 无缓冲channel:同步通信,发送和接收必须同时准备好
  • 有缓冲channel:异步通信,缓冲区满时发送阻塞,空时接收阻塞

select多路复用:同时等待多个channel操作。

同步原语(sync.Mutex互斥锁、sync.WaitGroup等待组、sync.RWMutex读写锁)#

为什么需要同步原语? 在并发编程中,多个goroutine同时访问共享资源时会产生竞态条件,导致数据不一致。

sync.Mutex(互斥锁)

  • 保证同一时间只有一个goroutine能访问共享资源
  • 两个方法:Lock()Unlock()
  • 使用后必须释放,否则会导致死锁

sync.RWMutex(读写锁)

  • 允许多个读操作或一个写操作
  • 读锁:RLock() / RUnlock()(共享锁)
  • 写锁:Lock() / Unlock()(互斥锁)
  • 适合”读多写少”的场景

sync.WaitGroup(等待组)

  • 等待一组goroutine完成工作
  • 三个方法:Add()Done()Wait()
  • 用于协调多个goroutine的执行顺序
var wg sync.WaitGroup

func main() {
    for i := 0; i < 3; i++ {
        wg.Add(1)        // 计数器+1
        go worker(i)
    }
    wg.Wait()           // 等待所有goroutine完成
}
go

原子操作替代简单锁

并发模式(生产者-消费者、扇入/扇出、Pipeline)#

生产者-消费者模式

  • 生产者-消费者模式是并发编程中最经典的模式之一,解决生产者和消费者速度不匹配的问题。
  • 就像食堂阿姨打饭和同学们吃饭,赚钱和花钱的关系是一样的。

扇入/扇出模式

  • 扇出:一个channel分发给多个goroutine处理(一产多消)
  • 扇入:多个channel合并到一个channel(多产一消)

Pipeline模式:将复杂任务分解为多个处理阶段,每个阶段通过channel连接,形成处理流水线。

带错误处理的并发模式

网络基础(TCP/IP协议、三次握手、端口概念)#

核心概念#

TCP/IP协议族是互联网通信的基础,就像现实世界的邮政系统一样,负责数据的可靠传输。

TCP/IP四层模型(类比快递系统):

  • 应用层 - 你的信件内容(HTTP、FTP、SMTP)
  • 传输层 - 快递包装和物流单(TCP、UDP)
  • 网络层 - 地址和路由(IP协议)
  • 网络接口层 - 运输工具(以太网、WiFi)

TCP vs UDP 核心区别

  1. TCP - 可靠传输,像打电话

    • 需要建立连接(三次握手)
    • 保证数据顺序和完整性
    • 自动重传丢失的数据
    • 适合:网页浏览、文件传输、邮件
  2. UDP - 不可靠传输,像发短信

    • 无需建立连接
    • 不保证数据到达顺序
    • 可能丢失数据包
    • 适合:视频流、游戏、DNS查询

三次握手详解#

TCP连接建立过程 - 就像确认双方都能正常沟通: tcp-connect.png

为什么需要三次握手?

  • 防止历史连接:避免网络延迟导致的重复连接请求
  • 同步序列号:确保双方都知道对方的起始序号
  • 确认双向可达:证明客户端和服务器都能正常收发数据

端口概念与应用#

端口的作用 - 就像公司的分机号,员工号:

  • 80: HTTP - 网页浏览
  • 443: HTTPS - 安全网页
  • 22: SSH - 安全远程登录
  • 53: DNS - 域名解析
  • 3306: MySQL - 数据库
  • 5432: PostgreSQL - 数据库
  • 6379: Redis - 缓存数据库

HTTP编程(net/http包、创建HTTP服务器、处理请求与响应)#

什么是HTTP?#

HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的一种网络协议,用于客户端和服务器之间的通信。

核心特点:

  • 无状态协议:每次请求都是独立的,服务器不保留之前请求的信息
  • 基于请求-响应模型:客户端发起请求,服务器返回响应
  • 应用层协议:建立在TCP/IP协议之上
  • 明文传输:数据不加密(HTTPS是加密版本)

HTTP请求-响应流程#

客户端 (浏览器/APP)       服务器 (Web服务)
     |                         |
     | --- HTTP请求  ------->  |
     |                         | 
     | <--- HTTP响应 --------  |
     |                         |
plaintext

HTTP请求组成#

GET /api/students HTTP/1.1          ← 请求行(方法 + URL + 协议版本)
Host: localhost:8080                ← 请求头(元数据)
Content-Type: application/json
Authorization: Bearer token123
                                   ← 空行分隔
{"name": "张三", "age": 20}         ← 请求体(可选,POST/PUT时有)
plaintext

HTTP方法语义:

  • GET:获取资源(查)
  • POST:创建资源(增)
  • PUT:更新资源(改)
  • DELETE:删除资源(删)
  • PATCH:部分更新

HTTP响应组成#

HTTP/1.1 200 OK                     ← 状态行(协议版本 + 状态码 + 描述)
Content-Type: application/json      ← 响应头(元数据)
Content-Length: 45
Date: Mon, 23 Oct 2023 08:00:00 GMT
                                   ← 空行分隔
{"id": 1, "name": "张三", "age": 20} ← 响应体(数据内容)
plaintext

常见状态码:

  • 200 OK:请求成功
  • 201 Created:资源创建成功
  • 400 Bad Request:客户端请求错误
  • 401 Unauthorized:未认证
  • 404 Not Found:资源不存在
  • 500 Internal Server Error:服务器内部错误

net/http包架构#

客户端请求

http.ServeMux (路由 multiplexer) 

http.Handler (处理器接口)

具体处理逻辑 (HandlerFunc或自定义Handler)

http.ResponseWriter (写回响应)
plaintext

核心组件说明#

1. 路由 (ServeMux)

  • 负责将不同的URL路径映射到对应的处理器
  • 可以创建多个路由,但通常一个应用使用一个主路由

2. 处理器 (Handler)

// Handler是一个接口,只需要实现一个方法
type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}
go

3. 处理器函数 (HandlerFunc)

// 函数签名,与ServeHTTP方法相同
type HandlerFunc func(ResponseWriter, *Request)
go

4. 请求对象 (Request)

  • 包含客户端的全部请求信息
  • 方法、URL、请求头、请求体等

5. 响应写入器 (ResponseWriter)

  • 用于构建和发送响应回客户端
  • 可以设置状态码、响应头、写入响应体

Websocket#

WebSocket是什么?

想象一下你和朋友打电话的场景:

  • HTTP:像发短信,每次都要建立连接→发送→断开,不能实时对话
  • WebSocket:像打电话,一次接通后双方可以随时说话,实现真正的实时对话

WebSocket核心特点

  • 一次握手,长久连接:客户端发起WebSocket请求,服务端同意后建立持久连接
  • 双向通信:服务端可以主动向客户端推送数据,不再需要客户端轮询
  • 低延迟:避免了HTTP每次请求的头部开销和连接建立时间
  • 协议升级:基于HTTP协议升级而来(HTTP 101状态码)

WebSocket握手过程

客户端请求:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade

服务端响应:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
plaintext

为什么需要gorilla/websocket库? Go标准库没有提供完整的WebSocket实现,gorilla/websocket是业界最成熟的选择:

  • 处理了WebSocket协议细节
  • 提供了连接管理、消息读写等高级功能
  • 有良好的错误处理和连接状态管理
Go并发编程
https://santisify.top/blog/other/go-concurrent-programming
Author santisify
Published at July 1, 2026
Comment seems to stuck. Try to refresh?✨