先听懂一个问题,
再回到代码。
文本按文件和调用链组织,饭点课按问题组织。不要求一一对应;每课都能跳回相关文本,相关文本也会列出可听的小课。
流程课
把多个文件串成一次完整过程,先建立整个系统的直觉。
两行 Python,怎么跑出 42?
跟一次 Python 与 Go 的查价调用,理解环境、工具、计算与结果交付。
↗1:44查价失败,怎样回到 Python 的 except?
跟一次普通同步执行,看 Go 的查价错误怎样经 JSON 桥接变成 Python RuntimeError,并被 try/except 捕获。
↗1:59PLM:Go 先准备,Python 原位领取
跟一组真实测试,看 PLM 怎样提前启动受信读取,又把结果和错误留到 Python 原调用点交付。
↗2:05Prefix:源码到齐前,先准备可读的前缀
沿一条 append-only 源码流,看 Host 怎样接收,Guest 怎样只准备安全的前缀,最后回到原调用领取结果。
↗1:31Prepared baseline:干净内存,整段恢复
沿 prepared.go 和 prepared_test.go 看 NewPrepared 怎样保存干净的 linear memory 基线,再让每轮新 Guest 恢复私有副本。
↗1:34COW:干净页先共享,写入后再分离
用三块抽象页看清 sealed memfd、两个 MAP_PRIVATE 映射,以及一次写入如何由 Linux 内核完成隔离。
↗2:17Guest 构建链:从固定输入到 Go 加载
沿真实 Makefile 和构建脚本,把 Host 工具链、Wasm 目标、嵌入文件和 Go 加载分开看。
↗1:31离线验收为什么要有 namespace?
跟一条离线验收脚本:先准备缓存,再让网络探针和后续检查留在同一个隔离子进程里。
↗知识小点
只解决一个疑问;遇到不懂的语法或机制,再用一小集补上。
Go 变量不会记住公式
用同一个函数块看清单变量 := 与 =:变量保存赋值当时算出的值,想更新结果必须再次计算。
↗1:20Go defer:先登记,返回前倒着执行
用同一个函数看清 defer 调用的参数求值、登记顺序和返回前的逆序执行。
↗1:21Go slice:复制描述,还是复制存储?
用两个 int 元素看清 b := a 只复制 slice 描述,而 make 加 copy 才建立独立的元素存储。
↗1:13Go map 里也能放函数
用一个小示意和真实源码,看工具名怎样在 map 里找到函数值,再带着参数得到结果或错误。
↗1:19Go channel:先写结果,再 close(done)
看清结果盒与通知 channel 的分工:先发布结果,再关闭 done;多个等待者都能继续。
↗1:29Go context:取消是通知,收尾靠等待
用一个无 sleep 的 Go 例子和项目真实代码,看 context 取消如何通知工具,以及 WaitGroup 怎样确认 worker 已经退出。
↗1:15Go defer:闭包读取的是哪个时刻的 x?
把 defer 的参数求值和闭包捕获放在同一个函数里,看清登记顺序、读取时机与返回前的后进先出。
↗1:27Go 接口:同一个方法,换一个实现
用一个可运行的小例子看懂 Go 接口的隐式实现,再对照项目里的 api.Module 与 Tool 用法。
↗1:20Go 指针:指向同一值,不自动拥有资源
用一个跑过的 int 指针例子分清同一份值、GC 管理的内存,以及软件约定的 Close 责任。
↗1:31Wasm ABI:ptr 是偏移,len 按字节
沿 execute 的真实返回路径,看清 Guest 线性内存中的字节区间、Wasm 偏移量、按字节计的长度,以及请求和结果缓冲区各自的 release。
↗1:21PyObject *:一份引用,谁来归还?
沿 guest/runtime.c 的真实调用,看新引用、借用数据、Py_DECREF 与 malloc/free 为什么不能混账。
↗1:59COW 内存:范围先留,可见长度再长
用一个 Wasm 实例看清 COW 内存的最大地址范围、稳定 base、可访问长度与超限失败;预留范围不等于 RSS。
↗