🐹 Go 语言速查手册

一份按「基础 → 中级 → 高级 → 应用」分层的速查。每个知识点都用一段最小可运行的代码说明,方便写代码前快速回血。
Go 的哲学:少即是多 —— 没有继承、没有泛型的历史包袱(1.18 后才加)、没有异常(用 error)、并发是头等公民。

基础 · 语法与类型 中级 · 接口与并发 高级 · 泛型 / 模式 / 性能 应用 · Web / CLI / 布局
① 程序骨架 ② 变量与常量 ③ 基本类型 ④ 复合类型 ⑤ 控制流 ⑥ 函数 ⑦ 结构体与方法 ⑧ 接口 ⑨ 错误处理 ⑩ 并发基础 ⑪ sync 同步原语 ⑫ 标准库 ⑬ 泛型 ⑭ Context ⑮ 并发模式 ⑯ 性能与内存 ⑰ 测试 ⑱ 应用速成

基础篇 · 语法与类型

写得出、读得懂。掌握这一层就能写脚本和简单服务。

程序骨架:package / import / main

package main // 可执行程序必须是 main 包 import ( "fmt" // 标准库包,双引号 "time" ) func main() { // 入口函数,无参数无返回值 fmt.Println("hello") }

要点:package main + func main() 才是可执行入口;库包用别的包名。导入未使用的包会编译报错。

一行式导入可简写:import "fmt"。多包用括号分组导入,末尾逗号不要也行(Go 会自动补)。

变量与常量

var a int = 10 // 显式声明 var b = 20 // 类型推断 c := 30 // 短声明,只能在函数内 var x, y int = 1, 2 // 多变量 m, n := 3, 4 const Pi = 3.14159 // 常量,编译期确定 const ( // 常量组 + iota 计数器 A = iota // 0 B // 1 C // 2 )
:= 是「声明并赋值」,左侧必须至少有一个新变量;它不能在包级(函数外)使用,包级只能用 var / const

基本类型

整型
int/int8/int32/int64uint 家族;byte=uint8,rune=int32(Unicode 码点)。
浮点 / 复数
float32/float64(默认 64);complex64/128
布尔 / 字符串
bool 只有 true/false;string 不可变、UTF-8、可按字节或 rune 遍历。
s := "你好Go" fmt.Println(len(s)) // 8:按字节数(中文 3 字节) for _, r := range s { // range 按 rune 迭代 fmt.Printf("%c ", r) // 你 好 G o }
不同长度的整型之间不能隐式转换,必须显式:int64(a)。这与 C 不同,是 Go「显式即清晰」的体现。

复合类型:数组 / 切片 / Map / 结构体

// 数组:长度是类型的一部分,很少直接用 var arr [3]int = [3]int{1, 2, 3} // 切片:动态数组,最常用。底层是 指针+len+cap sl := []int{1, 2, 3} sl = append(sl, 4) // 追加,可能重新分配 sl = sl[1:3] // 切片操作 [1,3) sl2 := make([]int, 0, 10) // 预分配 cap=10 // Map:哈希表,零值不可用作,必须 make mp := make(map[string]int) mp["a"] = 1 v, ok := mp["b"] // ok=false 表示不存在,不会 panic // 结构体 type User struct { Name string Age int }
nil map 读得到(返回零值)但写入会 panic,务必 make。切片底层数组被大切片引用而释放不掉,是常见内存泄漏点。

控制流:if / for / switch / range

// if 可直接带初始化语句 if v, err := f(); err != nil { return err } // Go 只有 for,没有 while for i := 0; i < 3; i++ {} // 经典 for cond {} // 当 while for {} // 死循环 for k, v := range sl {} // 迭代 // switch 默认自带 break,且条件可为任意类型 switch x.(type) { case int: fmt.Println("int") default: fmt.Println("other") }

range 迭代 map/slice 时取的是「值拷贝」,若想改元素要取地址或用索引。

函数:多返回值 / 命名返回 / defer / 变参

// 多返回值:Go 的习惯是 (结果, error) func div(a, b int) (int, error) { if b == 0 { return 0, errors.New("div by zero") } return a / b, nil } // 命名返回值 + defer 修改它(经典关闭资源范式) func f() (err error) { defer func() { err = recover() }() // 捕获 panic 写入 err return doSomething() // 等价于 return err } // 变参 func sum(nums ...int) int { return 0 }
defer 是栈式(后进先出),参数在「注册时」取值,但函数体在 return 后执行。常用于关闭文件、解锁、记录耗时。

结构体与方法(值 vs 指针接收者)

type Counter struct{ n int } // 值接收者:副本,不改原对象 func (c Counter) Get() int { return c.n } // 指针接收者:改原对象,且避免大对象拷贝 func (c *Counter) Inc() { c.n++ } func main() { c := Counter{} c.Inc() // Go 自动取地址 (&c).Inc() fmt.Println(c.Get()) // 1 }
经验法则:如果方法需要修改接收者、或接收者是大对象,用指针;否则看类型整体一致性 —— 同一个类型的接收者风格要统一。

中级篇 · 接口与并发

Go 的「鸭子类型」接口 + 轻量并发。这一层让你写出地道的 Go。

接口:隐式实现 / 空接口 / 类型断言

// 只要方法集匹配就算实现,无需 implements 声明 type Speaker interface { Speak() string } type Dog struct{} func (d Dog) Speak() string { return "woof" } // Dog 自动实现了 Speaker func main() { var s Speaker = Dog{} // 赋值时检查实现 fmt.Println(s.Speak()) var i interface{} = 42 // 空接口可装任何类型 if n, ok := i.(int); ok { // 类型断言 fmt.Println(n) } switch v := i.(type) { // 类型 switch case int: fmt.Println("int", v) default: fmt.Println("?") } }
Go 1.18+ 有 any(= 空接口)、comparable(可做 map key 的约束)。接口是「值 + 类型」二元组,含 nil 值的接口不等于 nil 接口 —— 经典坑。

错误处理:没有异常,只有 error

import ("errors"; "fmt") // 构造错误 err := errors.New("boom") err = fmt.Errorf("wrap: %w", err) // %w 可穿透 errors.Is/As // 检查 if err != nil { return err } // panic/recover 仅用于不可恢复的程序错误 defer func() { if r := recover(); r != nil { fmt.Println("recovered:", r) } }() panic("fatal")
不要用 panic 当普通错误。仅在初始化失败、不可继续时用。错误传播时优先 fmt.Errorf("...: %w", err) 保留链路。

并发基础:goroutine + channel

// goroutine:在函数调用前加 go,开销仅几 KB go doAsync() // channel:goroutine 间通信(CSP 模型) ch := make(chan int) // 无缓冲 buf := make(chan int, 10) // 有缓冲,cap=10 go func() { ch <- 1 }() // 发送 v := <-ch // 接收,会阻塞 close(ch) // 发送方关闭 v, ok := <-ch // ok=false 表示已关闭 // 单向 channel:限制方向,提升可读性 func producer(out chan<- int) {} // 只写 func consumer(in <-chan int) {} // 只读
「不要通过共享内存来通信,而要通过通信来共享内存。」—— 优先用 channel,而非 mutex + 共享变量。channel 关闭后不可再发送,否则 panic。

sync 同步原语

WaitGroup
等一组 goroutine 结束。Add/Done/Wait。Done 写在 defer 里。
Mutex / RWMutex
互斥 / 读写锁。读多写少用 RWMutex(RLock/RUnlock)。
Once
保证只执行一次。once.Do(init),常用于单例/懒加载。
Map
并发安全的 map,替代加锁的 map[string]any。
Pool
临时对象复用,缓解 GC 压力(见性能篇)。
atomic
无锁原子操作,比 mutex 轻。atomic.Int64 等。
var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(id int) { defer wg.Done() work(id) }(i) } wg.Wait() // 阻塞直到所有 Done

常用标准库速查

典型用途高频函数
fmt格式化输入输出Println/Sprintf/Printf/Scan
strings字符串处理Split/Trim/Contains/Replace/Builder
strconv字符串 ↔ 数字Atoi/Itoa/ParseFloat/FormatInt
time时间日期Now/Parse/Format/Add/After
sort排序Slice/Ints/Search
io / bufio流式读写Copy/Read/Writer/Scanner
os系统交互Open/Args/Exit/Getenv
encoding/jsonJSONMarshal/Unmarshal
net/httpHTTP 客户端/服务端Get/Post/HandleFunc/ListenAndServe
data, _ := json.Marshal(map[string]int{"a": 1}) var m map[string]int json.Unmarshal(data, &m) // 注意传指针

高级篇 · 泛型 / Context / 模式 / 性能

写出可复用、可扩展、高性能的生产级 Go。

泛型(Go 1.18+)

// 类型参数 [T any],约束写在 interface 里 func Max[T comparable](a, b T) T { if a > b { return a } return b } // 自定义约束 type Number interface { int | int64 | float64 } func Sum[T Number](ts []T) T { return ts[0] } // 内置约束:any, comparable, ~int 等 type Cache[K comparable, V any] struct { m map[K]V }
标准库已提供 slicesmapscmp 等泛型包(1.21+)。约束用 | 并集,~ 表示「底层类型」匹配。

Context:取消、超时、传值

// 超时控制:3 秒后自动取消 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() // 必须调用,释放资源 go func() { select { case <-time.After(5 * time.Second): fmt.Println("done") case <-ctx.Done(): // 被取消 / 超时 fmt.Println(ctx.Err()) // context deadline exceeded } }() // 传值:跨 API 透传请求作用域数据(别乱用) ctx = context.WithValue(ctx, "traceId", "abc")
Context 作为函数「第一个参数」贯穿调用链;不要存进 struct;WithValue 只放请求级元数据(traceId 等),不要放大对象。

并发模式

Worker Pool
固定 N 个 worker 从任务 channel 取活,限流防炸。
Fan-out / Fan-in
多 worker 分治,再汇总到一个 channel。
Pipeline
阶段间用 channel 串联,数据流式处理。
select 多路
select 同时等待多个 channel,配 default 防阻塞。
// worker pool 范式 jobs := make(chan int, 100) for w := 0; w < 3; w++ { go func() { for j := range jobs { // 通道关闭后自动退出 process(j) } }() }

性能与内存

pprof
import _ "net/http/pprof",访问 /debug/pprof 拿 CPU/heap 火焰图。
Benchmark
func BenchmarkX(b *testing.B) + go test -bench .
sync.Pool
复用临时对象,减少分配与 GC:Get/Put
atomic
计数器/标志用 atomic.Int64,免锁。
逃逸分析
go build -gcflags="-m" 看哪些变量逃到堆上。
预分配
make([]T, 0, n) 指定 cap,减少扩容拷贝。
var pool = sync.Pool{ New: func() any { return make([]byte, 1024) }, } buf := pool.Get().([]byte) defer pool.Put(buf) // 用完归还
Go 调度器是 GMP 模型(Goroutine/Machine/Processor),goroutine 在用户态调度,切换成本是线程的零头 —— 这是「并发是头等公民」的根基。GC 用三色标记法并发回收(详见本目录 golang-gc-tricolor.html)。

测试:表驱动 + Benchmark + Mock

// 文件 foo_test.go,函数名 TestXxx func TestDiv(t *testing.T) { tests := []struct{ a, b, want int }{ {6, 3, 2}, {0, 1, 0}, } for _, tt := range tests { if got := div(tt.a, tt.b); got != tt.want { t.Errorf("%d/%d=%d want %d", tt.a, tt.b, got, tt.want) } } } // 运行:go test ./... 覆盖率:go test -cover
接口让 Mock 极其简单:测试时传入一个「假实现」即可,无需框架。Benchmark 用 b.ResetTimer() 排除准备耗时。

应用篇 · 最常写的三类程序

把上面的语法落进真实场景:Web 服务、命令行、项目布局。

① Web 服务(net/http 原生)

func main() { mux := http.NewServeMux() mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "hello %s", r.URL.Query().Get("name")) }) http.ListenAndServe(":8080", mux) }
生产微服务常用 go-zero(本目录已有一整套教程:go-zero-basics / api / rpc / microservices)。需要更强路由用 ginecho 等第三方框架。

② 命令行 CLI(flag)

var name = flag.String("name", "world", "who to greet") var port = flag.Int("port", 8080, "listen port") func main() { flag.Parse() fmt.Printf("hi %s on %d\n", *name, *port) }

复杂 CLI 用 cobra;构建命令 go build -o app .,交叉编译 GOOS=linux GOARCH=amd64 go build

③ 标准项目布局

myproject/ ├── cmd/ // 各可执行程序入口 │ └── app/main.go ├── internal/ // 私有代码,外部不可 import │ ├── service/ │ └── repo/ ├── pkg/ // 可公开复用的库 ├── api/ // api/rpc 定义(go-zero 用 .api/.proto) ├── configs/ ├── go.mod └── Makefile
internal/ 是 Go 编译器强制的「私有边界」:外部模块无法 import 它里面的任何东西。这是 Go 管理可见性的首选手段。

一张表回顾分层能力

层级你该掌握的标志性语法
基础写得出程序var:=slice/mapfor/rangestruct
中级写地道 Gointerface{}errorgoroutine/channelsync
高级写生产级泛型contextworker poolpprofGMP
应用落地交付net/httpflaginternal/pkggo-zero