
Go 1.11 发布于 2018-08-24。这一版最重要的变化不是语法，而是把 Go Modules 带进主线：依赖管理从 GOPATH 时代开始转向模块化时代。

我对照了官方 release notes 和 Go 源码 tag。源码里 `api/go1.11.txt` 记录了 559 条公开 API 增量；标准库公开目录相对 Go 1.10 新增了 `syscall/js`，这与 WebAssembly 支持对应。

## 主要变化

### 1. `go.mod` 成为依赖边界

Go 1.11 的模块系统把“项目是什么”和“依赖哪个版本”写进 `go.mod`。模块路径定义导入根路径，`require` 记录依赖版本，`go.sum` 记录校验哈希。

```go
module example.com/app

require golang.org/x/text v0.3.0
```

它解决的是 GOPATH 时代最核心的问题：源码必须放在固定目录下，而且同一个依赖在不同项目里难以稳定选版本。模块模式下，项目目录可以放在任意位置，依赖版本由模块图决定。`GO111MODULE=on/auto/off` 则控制 Go 命令是否进入模块模式。

行为上，`go build`、`go test`、`go list` 会从当前目录向上查找 `go.mod`。找到后，当前模块就成为包加载和版本选择的边界。这个边界也影响 import path：模块内包的导入路径要以 module path 为前缀。

### 2. WebAssembly 进入官方端口

这一版新增 `GOOS=js GOARCH=wasm`，Go 程序可以编译成 WebAssembly 并在 JavaScript 宿主环境里运行。

```bash
GOOS=js GOARCH=wasm go build -o main.wasm
```

对应的标准库包是 `syscall/js`。它提供 `js.Value`、`js.Global`、`js.FuncOf` 等能力，用来访问 JavaScript 全局对象、调用 JS 函数、把 Go 函数暴露给 JS。它不是把 Go 变成前端语言，而是让 Go 能进入浏览器、边缘运行时和嵌入式宿主这类场景。

### 3. 构建缓存成为基础设施

Go 1.11 之后，构建缓存不再只是加速选项，而是 Go 命令正常工作的组成部分。编译结果、测试结果和包加载信息可以复用，日常 `go test`、`go build` 的增量体验更稳定。这也让工具链更依赖确定性的输入和输出。

缓存命中取决于源码、构建参数、环境和依赖内容。对测试来说，如果包源码和测试输入没有变化，`go test` 可以直接复用之前结果。这个行为让本地反馈更快，也让“测试是否真的重新执行”这个问题变得可观察：输出里会出现 `(cached)`。

### 4. 标准库补强集中在安全、网络和诊断

TLS、X.509、HTTP、模板、`runtime/trace`、`runtime/pprof` 都有改进。源码 API 文件里 `debug/elf` 的新增常量很多，说明 Go 对平台和二进制格式识别能力继续扩展。整体看，Go 1.11 是“工程基础设施”版本，而不是语法版本。

这些 API 对日常代码的影响是间接的：TLS 和 X.509 影响默认安全行为，HTTP 改进影响服务器和代理，trace/pprof 改进影响线上诊断。Go 1.11 的新增包虽然只有 `syscall/js`，但工具链和模块系统的影响远大于单个 API。

## 语言与规范

Go 1.11 没有引入新的语言语法。规范层面的重点是导入路径限制：包如果带有 `go.mod` 声明的模块路径，就要按模块路径导入，减少同一代码用多个路径引用带来的类型不一致问题。

类型一致性是这里的关键。Go 里同名类型如果来自不同 import path，就是不同类型。模块路径收紧后，可以减少 `example.com/lib/pkg` 和本地相对路径同时引用同一份代码造成的类型割裂。

## 工具链与运行时

Go Modules 是这一版的主线。`GO111MODULE=on/auto/off` 控制模块模式，`go.mod` 记录模块路径和依赖版本，`go.sum` 记录校验信息。虽然当时仍然是早期能力，但已经确定了后来 Go 依赖管理的基本形态。

端口方面，`GOOS=js GOARCH=wasm` 可以把 Go 程序编译为 WebAssembly。RISC-V 的 `GOARCH` 值也被预留，方便生态提前适配。

工具方面，`go test`、`go vet`、`go trace`、`godoc`、`gofmt` 都有改进。构建缓存成为必需能力，不再推荐通过关闭缓存来规避问题。

## 标准库与新增包

源码目录差异显示，Go 1.11 新增公开包：

- `syscall/js`：给 WebAssembly 程序访问 JavaScript 宿主环境。

值得注意的库变化包括：

- `crypto/tls` 和 `crypto/x509` 改进证书、握手和验证行为。
- `net/http`、`net/http/httputil` 增加若干服务端和代理相关能力。
- `runtime/trace`、`runtime/pprof` 改进诊断能力。
- `debug/elf` 在 API 文件中有大量新增常量，反映平台和二进制格式支持扩展。

## 小版本特殊变化

Go 1.11 系列共有 13 个小版本，主要围绕模块早期问题、安全和工具链稳定性展开。

这些安全修复主要落在三个入口。第一是 `go get`：它会访问远程仓库、解析 import path、调用 VCS 工具，属于供应链入口，问题可能影响依赖获取过程。第二是 `crypto/x509`：证书链、主机名和约束验证一旦有漏洞，TLS 连接可能信任不该信任的证书。第三是 `net/http`、`net/url`：HTTP 请求解析、URL 规范化和重定向边界如果处理不一致，容易引出请求走私、路径绕过或错误的安全判断。

- `go1.11.3` 修复了 `go get` 和 `crypto/x509` 的安全问题，是模块下载链路和证书验证都需要关注的一次小版本。
- `go1.11.4` 修掉了 `go1.11.3` 引入的回归：包含 `...` 的 import path pattern 会让 `go get` 出问题。这个例子说明 Go 早期模块和包模式匹配仍在快速打磨。
- `go1.11.8` 是误发布版本，内容基本等同 `go1.11.7`；真正想发布的修复落在 `go1.11.9`。
- `go1.11.9` 专门修复旧 GNU/Linux 上预编译二进制结合 cgo 链接失败的问题。
- `go1.11.10` 和 `go1.11.13` 都包含安全修复，前者涉及 runtime，后者涉及 `net/http` 和 `net/url`。
- 其余小版本主要集中在 compiler、linker、runtime、`go` 命令、`crypto/x509`、`encoding/json`、`net/http`、`reflect` 等组件。

## 参考

- [Go 1.11 Release Notes](https://go.dev/doc/go1.11)
- [Go Release History](https://go.dev/doc/devel/release)
- [Go 1.11 source tag](https://go.googlesource.com/go/+/refs/tags/go1.11)
- [api/go1.11.txt](https://go.googlesource.com/go/+/refs/tags/go1.11/api/go1.11.txt)

