golangci-lint Go 代码质量
golangci-lint 聚合多个 linter 并行运行。配置文件 .golangci.yml 控制启用 linter。CI 集成保证代码质量。本文配置项目并在 CI 中运行。
Go io.Reader 和 io.Writer 接口
Go 的 io.Reader 和 io.Writer 是流式 I/O 的抽象基础。标准库大量函数基于这两个接口。组合小接口成大功能。本文自定义 Reader 加密数据。
Go embed 静态文件嵌入
Go 1.16 embed 在二进制中嵌入静态文件部署时不需要额外文件。//go:embed 指令在构建时嵌入。支持文件和目录。本文用 embed 打包 HTML 模板。
Go race detector 数据竞争检测
Go 的 -race 标志编译后运行时检测数据竞争。发现 goroutine 间无锁共享变量访问。性能下降 5-10 倍用于测试。本文用 race detector 定位并发 bug。
Go 泛型在集合操作中的应用
Go 1.18 引入泛型用类型参数实现可复用的集合操作。约束 comparable/constraints.Ordered。本文实现一个通用的 Filter 和 Map 函数。
GORM Go 语言 ORM 的 CRUD 操作
GORM 是 Go 最流行的 ORM。AutoMigrate 自动建表。链式调用构建查询。Preload 预加载关联数据。本文用 User 模型展示 GORM 的常用 CRUD 操作。
Go 中 reflect 反射包的基本使用
reflect.TypeOf 获取类型reflect.ValueOf 获取值。反射绕过了 Go 的编译时类型检查有运行时开销。只有在不确定类型时才需要用反射。
Go 中 encoding/csv 读写 CSV 文件
csv.NewReader 读取 CSV文件支持自定义分隔符和注释行。csv.NewWriter 写入 CSV。本文展示带标题行的 CSV 读写方法。
Go 中 math/rand 生成随机数
math/rand 生成伪随机数需要先设置种子。rand.Intn(n) 生成 0 到 n-1 的随机整数。rand.Shuffle 随机打乱切片。本文展示随机数生成的各种用法。
Go 中 url.Values 构建查询参数
url.Values 是 map[string][]string 类型用 Add 方法添加参数Encode 方法编码成查询字符串。适合构建 GET 请求的 URL 参数。
Go 中 iota 枚举常量的用法
iota 在 const 块中逐行递增。const (A = iota B C) 从 0 开始。配合移位操作可以生成位掩码。本文展示 iota 在枚举定义中的多种模式。
Go 中 strconv 包的类型转换
strconv.Atoi 字符串转整数strconv.Itoa 整数转字符串。ParseFloat/FormatBool 等处理其他类型。转换失败返回 error。本文列出常用转换函数。
Go 中 strings 包常用函数
strings.Contains/HasPrefix/TrimSpace/Split/Join/Replace 是字符串处理的核心函数。本文展示这些函数在文本处理中的常见组合用法。
Go 中的接口型函数 Function Interface Pattern
Go 通过将函数作为接口的实现定义函数类型并实现该接口的方法。net/http.HandlerFunc 是典型例子。本文展示这种灵活的设计模式。
Go 中 sort 包的排序接口
sort.Interface 需要实现 Len/Less/Swap 三个方法。sort.Slice 用闭包更方便。sort.Search 二分查找有序序列。本文展示 sort 包的常用方法。
Go 中 recover 只能捕获本 goroutine 的 panic
defer recover() 只能捕获同一 goroutine 中的 panic。在 go func 中发生的 panic 不能被外层 recover 捕获导致程序崩溃。需要在每个 goroutine 中处理。
Go 中 init 函数的执行顺序
Go 的 init 函数在包初始化时自动执行不能被显式调用。同一包内的 init 按文件名字典序执行依赖的包先初始化。本文解释 init 的执行规则。
Go 中的空结构体 struct{} 用途
struct{} 不占任何内存用作 channel 的信号(chan struct{})或 Set 的 map 值(map[string]struct{})。本文展示空结构体的实际应用场景。
Go 中 channel 的 close 和 range 操作
close(ch) 通知接收方不会再发送新数据。range ch 持续接收直到 channel 关闭。只应该由发送方 close channel向已关闭的 channel 发送会 panic。
Go panic 时打印完整的调用栈
defer recover() 捕获 panic 后调用 debug.Stack() 可以打印完整的 goroutine 调用栈方便定位问题。本文实现一个 recoverWithStack 辅助函数。
Go 类型断言和类型 switch
类型断言 x.(T) 从接口值提取具体类型。配合逗号 ok 形式可以避免 panic。type switch 配合 fallthrough 处理多种类型。本文展示类型断言的各种写法。
Go 中 new 和 make 的区别
new 返回指向零值的指针make 初始化 slice/map/channel 并返回非零值。new 只分配内存不初始化make 分配并初始化。本文用代码对比两者的行为差异。
Go 中 struct 作为 map 的 key
Go 的 map key 必须是可以比较的类型 struct 如果所有字段都可比较可以作为 key。包含 slice 或 map 字段的 struct 不能作为 key。本文用代码验证哪些 struct 可以作为 key。
Go 命名返回值的 defer 陷阱
Go 的 defer 可以修改命名返回值但这段代码在 return 求值之后才执行 defer 实际修改无效。理解 defer return 和返回值的执行顺序是避免这类问题的关键。
Go 切片扩容策略理解 append 的内存行为
Go 切片在 append 超过容量时会重新分配底层数组容量翻倍(小切片)或增长 25%(大切片)。理解这个机制有助于减少不必要的内存分配和复制。本文用代码展示容量的增长曲线。
Go defer 在 for 循环里资源泄漏
defer 在函数返回时执行不是在 for 循环结束时执行。在循环里 defer 文件关闭会导致文件句柄在整个函数执行期间无法释放。解法是在循环里用匿名函数包裹 defer。
Go panic 和 recover 不是异常处理
Go panic 和 recover 不是异常处理是开发中经常遇到的问题。本文从实际场景出发分析原因并给出可操作的解决方案适合正在排查这个问题的开发者参考。
Go 的 time.Sleep 在测试中的替代方案
测试中为了等 goroutine 执行完就加 time.Sleep 这不是可靠做法。慢的时候等不夠快的时候浪费时间。用 sync.WaitGroup chan 或 errgroup 才是正确方式。本文对比用 Sleep 和用 WaitGroup 的测试稳定性和执行速度。