PPysolate SpineREAD THE CODE · UNDERSTAND THE SYSTEM
课程与章节
CODE READING / 27

Go 依赖与校验记录

go.mod / go.sum

本章目录
配套饭点图解 · 1 节(按需展开)

先回答一个问题:执行 go run、go test 或 go vet 时,Go 到底从哪里得到代码,离线检查又阻断了哪一段?答案要放回整条产物流转中看:

go.mod / go.sum
        ↓ Go module 解析与校验
本机 module cache + 本地 Go toolchain
        ↓ go run / go test / go vet
Go Host 程序与检查结果

这条链只负责 Go 部分。Guest 的 CPython、WASI SDK、wasm-tools、wasmtime 和 wasi-vfs 走 tools/build-inputs.lock.json;站点的 Node/pnpm 依赖又由 site/ 自己的锁文件管理。三套输入最后可能在一次 make offline 中同时被消费,但不会由同一个锁文件提供。

1. go.mod 描述什么

go.mod · L1–L7 · 打开完整源码

module pysolate-spine

go 1.25.0

require github.com/tetratelabs/wazero v1.11.0

require golang.org/x/sys v0.38.0

go.mod 给 Go 编译器和模块解析器三个关键信息:模块路径 pysolate-spine、Go 1.25.0 的解释基线,以及两个直接模块依赖。模块路径是导入和模块识别使用的名字,不要求等于 Git remote URL。go 1.25.0 也不会把 Go 编译器放进仓库;真正执行命令时,机器上仍要有可用的 Go toolchain。离线流程设置 GOTOOLCHAIN=local,因此 Go 不会为了满足别的版本要求而自动取得远程 toolchain。

github.com/tetratelabs/wazero v1.11.0 进入 Runner、bridge、prepared 等 Go 路径,负责 Wasm runtime、编译、实例化、WASI 和调用接口。它不是标准库,也不是 dist/spine.wasm 本身。golang.org/x/sys v0.38.0 为 Linux COW 路径提供 Unix 系统接口;平台文件选择决定哪些代码参与当前平台的编译,但模块声明仍需完整。

两个 require 块各只有一项。空行是排版分组,不代表两个不同生命周期,也不代表第二项在运行时才可选。当前文件没有 // indirect,所以这两项都按直接依赖声明。

这里的“声明”与“已有输入”要分开:go.mod 锁定可接受的模块版本,却不包含模块源码;它也不能证明本机缓存已经准备好。

2. go.sum 是内容校验记录

go.sum · L1–L4 · 打开完整源码

github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA=
github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=

go.sum 用成组记录保存两个模块的摘要:每个版本都有一条模块内容摘要,另有一条带 /go.mod 后缀的模块描述文件摘要。/go.mod 不是第三个依赖,而是被校验对象的类型;h1: 后面的字符串是 Go 模块摘要,脚本和 Go 命令会使用完整值,本章不重复抄录长数据。

因此,go.mod 说明“需要哪个模块版本”,go.sum 帮助 Go 判断取到的模块内容是否与记录一致。go.sum 不嵌入依赖源码,也不是密码表或完整供应链证明。GOSUMDB=off 只关闭外部 checksum database 查询,不关闭本地摘要比较,更不能单独证明依赖来源安全。

当前四行正好覆盖两个 Go 模块和两类摘要。CPython、WASI 工具、npm 包以及它们的完整第三方依赖树不在这里;它们属于另外的输入边界。

3. 从 Go 依赖到本地产物

在根目录执行 make demo、make explain、make prefix 或 make prepared 时,Make recipe 调用 go run ./cmd/demo ...。Go 先编译当前模块,读取 module cache 中的 wazero 和 x/sys,再启动 Host 程序;用户的 examples/order.py 是这次运行的输入,不会因此写入新的 Guest Wasm。

make check 仍消费这套 Go 输入,但它还会顺序执行 Go 测试、Guest 侧 Python 单测和 go vet。所以“Go 依赖已就绪”只说明第一类命令可能运行;真实 Guest 测试还需要非空的 dist/spine.wasm,站点构建还需要 Node/pnpm 依赖。

make guest 不通过 Go module 生成 Guest。它消费 build/inputs 中的本地 CPython/WASI 工具和静态库,另行执行 C 编译、链接、Python 文件打包与 Wasm 验证。要理解那条交接,继续读 构建入口、构建输入 和 Guest 构建。

4. 离线边界

tools/offline-check.sh 为 Go 导出三项环境约束:

  • GOPROXY=off:不从 Go module proxy 获取模块;
  • GOSUMDB=off:不访问外部 checksum database;
  • GOTOOLCHAIN=local:不自动下载或切换远程 toolchain。

这些变量只改变 Go 的依赖和 toolchain 行为。真正的网络阻断由外层隔离完成:Linux/Ubuntu 路径用 user namespace 加 network namespace 启动子进程,随后用 socket 探针确认固定地址不可达;macOS 路径使用 sandbox-exec。因此离线成功需要同时满足两件事:module cache 和其他构建输入已经在本机,运行命令的子进程确实没有外部网络。

如果 module cache 缺少 wazero,GOPROXY=off 不会等待或偷偷补齐,而应让命令明确失败。反过来,cache 存在也只表示输入可能可用;本次命令是否成功还取决于 Go 版本、源码、Guest artifact 和站点依赖。

5. 读完后应能回答

  1. 为什么 go.sum 同一版本有模块摘要和 /go.mod 摘要两行?
  2. 为什么删除 go.sum 不能把 wazero 源码变进 go.mod?
  3. 为什么离线检查既要设置 GOPROXY=off,又要用 Ubuntu network namespace 做 socket 探针?

下一步沿 Makefile 看这些不同输入怎样被目标串起来;本章只覆盖 go.mod 和 go.sum 的声明与校验记录,没有下载依赖、执行 Go 命令或进行离线验收。依据当前工作树源码,未对本机 cache 完整性和实际命令结果作现场验证。