# Go 1.27 核心速查

Source: https://codewiki.com/zh/cheatsheets/go/

## 声明与控制流

- `package main` — 把可执行程序的入口代码放在 main 包中
- `var count int` — 声明一个初始化为零值的整数
- `name := "gopher"` — 在当前代码块中声明局部变量并推断类型
- `left, right = right, left` — 先计算右侧两个表达式，再交换变量值
- `for i := range 10 { use(i) }` — 让 i 从零迭代到九
- `if value, ok := lookup(); ok { use(value) }` — 根据结果和状态分支，并限制变量作用域

## 函数与方法

- `func add(a, b int) int { return a + b }` — 声明参数类型合并书写的函数
- `func load(id string) (Item, error)` — 同时返回值与错误
- `func join(parts ...string) string` — 接收任意数量的尾部参数
- `func (c Counter) Value() int` — 声明使用值接收者的方法
- `func (c *Counter) Increment()` — 使用指针接收者修改所引用的值
- `func (s Stream[T]) Map[U any](f func(T) U) Stream[U]` — 在 Go 1.27 中声明方法专属的类型参数

## 结构体与接口

- `type User struct { ID int; Name string }` — 定义带有导出字段的结构体
- `user := User{ID: 7, Name: "Ana"}` — 按字段名构造结构体
- `type Reader interface { Read([]byte) (int, error) }` — 描述一项必需行为
- `type ReadWriter interface { io.Reader; io.Writer }` — 通过嵌入组合接口
- `var _ io.Reader = (*bytes.Buffer)(nil)` — 在编译期检查接口是否实现
- `value, ok := input.(string)` — 断言动态类型，类型不符时也不 panic

## 切片与 Map

- `items := make([]Item, 0, capacity)` — 创建长度为零并预留容量的切片
- `items = append(items, value)` — 保留 append 返回的切片
- `clone := slices.Clone(items)` — 把元素复制到独立的底层数组
- `counts := make(map[string]int)` — 创建以可比较字符串为键的可写 Map
- `count, ok := counts[key]` — 区分键不存在与存储的值为零
- `delete(counts, key)` — 删除键；键不存在也不会报错
- `keys := slices.Sorted(maps.Keys(counts))` — 按确定的排序顺序收集 Map 的键

## 错误与清理

- `if err != nil { return fmt.Errorf("load %q: %w", id, err) }` — 添加上下文，同时保留错误链
- `errors.Is(err, fs.ErrNotExist)` — 在包装错误与组合错误中匹配目标
- `var pathErr *fs.PathError; errors.As(err, &pathErr)` — 提取第一个类型匹配的错误
- `errors.Join(errs...)` — 把非 nil 错误合并成一个可遍历的错误
- `defer file.Close()` — 在外围函数返回时执行清理
- `defer func() { if r := recover(); r != nil { handle(r) } }()` — 仅在同一 goroutine 的延迟展开期间恢复 panic

## Goroutine 与通道

- `go process(job)` — 并发启动调用，不等待其结果
- `jobs := make(chan Job, 8)` — 创建最多缓冲八个值的通道
- `jobs <- job` — 发送值；没有接收者或缓冲空间时阻塞
- `job, ok := <-jobs` — 接收值，并检测已关闭通道是否排空
- `close(jobs)` — 发出不再发送值的信号；由发送方关闭
- `select { case result := <-done: use(result); case <-ctx.Done(): return ctx.Err() }` — 等待结果或取消信号

## Context 与同步

- `ctx, cancel := context.WithTimeout(parent, 2*time.Second); defer cancel()` — 设置期限，并在所有退出路径释放资源
- `ctx, cancel := context.WithCancelCause(parent)` — 派生一个由取消函数记录错误原因的 Context
- `context.Cause(ctx)` — 读取记录的取消原因
- `var wg sync.WaitGroup; wg.Go(task); wg.Wait()` — 启动一个不会 panic 的任务并等待它完成
- `mu.Lock(); defer mu.Unlock()` — 在函数的所有退出路径解锁临界区
- `once.Do(initialize)` — 确保初始化在多个 goroutine 间最多执行一次
- `value := counter.Add(1)` — 以原子方式递增强类型原子计数器

## I/O 与编码

- `reader := bufio.NewReader(source)` — 在 io.Reader 外增加读缓冲
- `n, err := io.Copy(dst, src)` — 流式复制字节，直到 EOF 或首次出错
- `data, err := io.ReadAll(io.LimitReader(src, limit))` — 把最多 limit 个字节读入内存
- `data, err := json.Marshal(value)` — 把受支持的 Go 值编码为 JSON
- `err := json.Unmarshal(data, &dst)` — 把 JSON 解码到指针目标
- `before, after, found := strings.Cut(text, separator)` — 只分割一次，并报告分隔符是否存在
- `//go:embed templates/*.html` — 把匹配文件嵌入紧随其后的变量

## HTTP 与 SQL

- `mux.HandleFunc("GET /users/{id}", handler)` — 按一种 HTTP 方法和路径模式路由
- `id := r.PathValue("id")` — 读取具名的 ServeMux 路径通配值
- `req, err := http.NewRequestWithContext(ctx, method, url, body)` — 把取消与期限绑定到出站请求
- `resp, err := client.Do(req)` — 发送请求；先检查 err，再使用 resp
- `defer resp.Body.Close()` — 在 Do 成功后释放响应体
- `err := db.QueryRowContext(ctx, query, args...).Scan(&dst)` — 执行预期返回一行的查询并扫描结果
- `tx, err := db.BeginTx(ctx, nil)` — 启动受 Context 控制的事务

## 模块与构建

- `go mod init example.com/project` — 以导入路径前缀创建模块
- `go get example.com/module@v1.2.3` — 以准确版本添加或升级依赖
- `go mod tidy` — 根据包导入同步 go.mod 与 go.sum
- `go fmt ./...` — 格式化模块中的所有包
- `go vet ./...` — 在整个模块运行标准静态分析器
- `go generate ./...` — 运行 go:generate 指令指定的源码生成器
- `go build ./...` — 编译所有包，但不安装

## 测试与模糊测试

- `func TestLoad(t *testing.T)` — 声明可被 go test 发现的测试
- `t.Run(name, testCase)` — 以 func(*testing.T) 运行具名子测试
- `t.Cleanup(release)` — 在测试及其子测试结束后执行清理
- `go test -race ./...` — 使用竞态检测器运行所有测试
- `go test -coverprofile=cover.out ./...` — 写出语句覆盖率报告
- `func FuzzParse(f *testing.F)` — 声明带有种子语料库的模糊测试
- `go test -fuzz=FuzzParse -fuzztime=30s` — 对一个匹配目标进行三十秒模糊测试

## 基准测试与性能剖析

- `func BenchmarkEncode(b *testing.B) { for b.Loop() { encode(input) } }` — 每轮测量一次操作，循环外准备不计时
- `b.Run(name, benchmarkCase)` — 运行具名子基准测试
- `b.RunParallel(func(pb *testing.PB) { for pb.Next() { work() } })` — 把基准测试迭代分配给多个 goroutine
- `go test -run=^$ -bench=. -benchmem -count=10` — 跳过测试，重复收集耗时与内存分配结果
- `benchstat old.txt new.txt` — 以统计方法比较基准测试样本
- `go test -run=^$ -bench=. -cpuprofile=cpu.prof` — 在基准测试运行时采集 CPU 样本
- `go tool pprof -http=:0 cpu.prof` — 在本地 Web 界面检查性能剖析文件
