探索 Go 1.24 中新的“go tool”支持

主要观点:Go 1.24 引入新的“工具”支持,可将 Go 编写的工具作为项目依赖轻松使用,如golangci-lintprotoc-gen-go
关键信息

  • 基本用法:添加工具类似标准运行时依赖,需加-tool标志,添加后可通过go tool <name>访问,go tool还有其他用法如列出所有工具、执行工具、打印工具路径、使用-modfile指定go.mod文件等,工具会出现在go.mod中。
  • 问题

    • 构建缓慢:用户定义工具每次使用时都需编译,即使小工具首次使用也需几秒,大工具可能需几分钟,虽然后续执行会缓存,但大工具仍有开销,如goimportstrivy的对比。Go 1.24 有缓存优化但go tool仍比go run慢,通过追踪发现确定缓存命中消耗时间较多,禁用缓存优化后差异更明显。
    • 共享依赖状态:工具的依赖会出现在go.mod/go.sum中,可能导致项目依赖和工具依赖混淆,影响依赖管理,且主项目和工具必须共享每个依赖的版本,可能导致微妙的错误或构建失败。
    • 冗长的使用方式:所有 Go 工具必须通过go tool <name>执行,而不是直接使用<name>
    • 仅支持 Go 工具:大多数项目可能依赖非 Go 工具,此解决方案无法满足。
  • 缓解措施和实际使用:提出一种工具管理策略,通过在tools/<toolname>下的脚本调用go tool <toolname>解决“冗长使用”问题,为每个工具设置独立的go.mod文件解决“共享依赖状态”问题,利用go tool -n获取二进制路径并缓存解决“构建缓慢”问题,通过哈希go.modgo.sumgo env构建哈希键进行缓存,在实际执行中添加了额外的复杂性但提高了性能。还可通过go tool -modfile共享go.mod
    重要细节:文中通过各种基准测试和示例展示了不同工具在各种情况下的性能差异和问题,如goimportstrivy的执行时间对比等,详细介绍了缓解措施的实现方式和代码示例。
阅读 7
0 条评论