Files
go-omni/reports/copyxAcceptance.md

5.3 KiB
Raw Blame History

v0.19 copyx 与映射移除验收

日期:2026-09-25。环境:Apple M2 Max、darwin/arm64、Go 1.27.1,基准默认 GOMAXPROCS=12。最低支持版本另用 Go 1.22.12 验证 copyx 与可运行示例。

范围与行为

本轮新增可选 Go 工具包并删除原映射配置/生成机制,没有修改接入项目代码、数据库或线上服务。没有新增第三方依赖,没有内置工资、金额或权限规则;工资只是生成器的独立通用验收 fixture。

场景 验证内容
浅/深复制 值、结构、指针、数组、map、slice、interface;浅共享与深隔离分别验证
空值与精度 nil 与空集合、默认保留 false/0、显式 nil/skip 策略;不兼容类型不能借 nil/零值绕过检查
可变引用 原指针/map、子切片、零长度但有容量的视图、源元素指针、私有子引用、其他字段的引用均拒绝
自定义函数 字段改名、精确类型对、金额私有状态复制、nil interface;重复/冲突配置拒绝
失败语义 errors.Is 保留 cause、目标不提交部分结果、嵌入目标指针不提前修改
对象图 指针/map/slice 循环,重复引用;循环指针根压成值结构拒绝
并发与资源 同一 Copier 64 goroutine 各复制 20 次,race;深度/节点/估算分配超限拒绝;锁/资源/函数等明确限制
真正生成的消费者 三端工资公共字段,Money scalar,大数精度/舍入、非法金额、缺失/null/零值、完整表单、错误码与错误链
维护成本 公共字段新增:改一处契约和一处独立业务结构;三个接口共用 helper,不增加拷贝规则
生成与生命周期 重复 generate/check/dry-run 保留业务文件;工厂异常、初始化/监听失败及资源关闭由既有回归验证
移除与 workspace 旧配置/旧生成文件阻断且不写入,明确迁移后所有权清理;workspace 失败不部分更新服务

FuzzClone 使用动态 JSON 容器、随机 bytes 和嵌套 slice,验证值一致与引用隔离。输入超过 1 KiB 时截取继续验证,运行 30 秒、4 workers:4,237,917 次执行,未发现失败。这不等于所有形状都已 fuzz;循环、类型转换及资源拒绝另外用定向用例覆盖。

全量 46 个测试包通过 race 回归(含实际生成项目),vet/build、Go 1.22.12、示例运行与生成漂移检查均通过。

可复现命令

GO_OMNI_SCAFFOLD_INTEGRATION=1 go test -race -count=1 ./...
go vet ./...
go build ./...
GOTOOLCHAIN=go1.22.12 go test ./copyx ./examples/copying
go test ./copyx -run '^$' -fuzz FuzzClone -fuzztime 30s -parallel 4
go test ./copyx -run '^$' -bench . -benchmem -benchtime 300ms -count 3
go run ./examples/copying
go run ./cmd/go-omni api generate --dir examples/managedService --check
# examples/managedService 中另执行 go test -race ./... 与 go build .

全量回归包含真实临时生成项目,集成测试的子进程使用 go test -race / go build,并不只比较生成字符串。基准测量时没有同时运行本轮 fuzz 或全量测试;原始三轮结果见 copyxBenchmark.txt。

性能与分配

下表取三轮中位数。构造器复用与一次性调用都包含真实复制;fields1000 指整数 slice 的长度,不是 1,000 个结构字段。所有深拷贝保留引用检查。

场景 中位耗时 B/op allocs/op
相同结构浅拷贝(含引用字段) 85.8 ns 96 2
3 字段跨结构改名,复用 Copier 697.5 ns 168 7
相同跨结构,每次构建 Copier 1,181 ns 1,120 17
嵌套结构 + 1 个整数 + map,深拷贝 2,758 ns 1,368 42
嵌套结构 + 100 个整数 + map,深拷贝 2,787 ns 2,256 42
嵌套结构 + 1,000 个整数 + map,深拷贝 3,806 ns 9,552 42
64 KiB byte slice 深拷贝 5,780 ns 65,768 9
100 项 map,每项含整数 slice 88,859 ns 87,704 1,554
自引用循环对象深拷贝 2,128 ns 640 26
converter 新建 slice 并通过检查 539.7 ns 280 10
converter 返回原 slice 被拒绝 383.8 ns 320 11

并行循环对象基准中位 515.2 ns/op 是多核聚合吞吐均摊,不是单请求延迟。复杂 map 的多次图扫描、字段路径和反射分配明显更贵;不据此宣称运行时工具快于手写赋值。热点复用 Copier;大对象和高频映射应按实际业务结构衡量是否改用直接 Go。

优化只包括不可变类型元数据缓存、纯值快速路径、纯值 slice 批量复制;没有去掉深拷贝别名检查。内置估算分配上限 64 MiB 不是硬堆内存隔离,converter 的外部分配及副作用不受该预算控制。

边界

  • 新方式在运行时做类型与覆盖检查,不再有旧映射生成时的静态保证;字段变更要运行实际类型对测试。
  • converter 是受信项目代码,必须只读输入;不能自动回滚其副作用、证明其未共享外部全局对象,或强杀无限循环。
  • 当前记录是本机库/生成器验收,不是线上服务吞吐、Linux soak、真实业务数据库回归或 OSS/R2 云账号验收。本轮没有对线上服务器施压。
  • 旧消费者仍需按 COPY.md 迁移,不会被这次框架发布自动修改。