Go 的错误是普通的值,返回之后由你检查。学会给错误包装上下文,用 errors.Is 和 errors.As 找到根因,一次合并多个错误,并把 panic 和 recover 留给真正的 bug。
Go 接口是一组方法,任何拥有这些方法的类型都自动满足它,不用声明。讲清方法集、Stringer、io.Reader、类型选择,以及为什么装着 nil 指针的 error 不是 nil。
Go 字符串是只读的字节序列,通常是 UTF-8。看清这一点,len 数的是字节、索引得到字节、range 得到 rune、切片会把一个字符切成两半,就都说得通了。
Go 的 map 按键存值,靠哈希来查找。弄清读取不存在的键为什么得到零值,写入 nil map 为什么会 panic,遍历顺序为什么每次运行都不一样。
Go 切片是一扇小窗口,背后的数组才真正存放数据。看清这扇窗口,len、cap、append,以及两个切片互相修改的 bug 就不再神秘。
Go 函数可以返回多个值,可以作为闭包带着变量走,还能用 defer 安排清理工作。本文逐一讲解,包括延迟调用的执行顺序,以及参数在什么时候确定。
Go 的流程控制只靠 if、唯一的循环关键字 for,以及默认不贯穿的 switch。本文讲解每种写法、Go 1.22 让每次迭代拥有独立循环变量的改动,以及带标签的 break。
Go 的每个变量都从零值开始,数字从不自动转换类型,常量比变量更灵活。本文讲解 var、:=、定长整数、溢出、iota,以及用来查看值的 Printf 格式动词。
写第一个 Go 程序,只需要一个命令行工具、一个 go.mod 文件和一个名为 main 的包。本文讲清 go run、go build、gofmt 和 go vet 各自做什么,以及 Go 为什么拒绝编译带有未使用导入的代码。