Go 库设计原则:从代码仓库到资源管理
编程涉及创建应用程序及其支持的库。库是可共享资源的集合,主要是源代码。区分术语有助于设计健壮的组件。
代码仓库包含文件系统中的代码文件。Go 中的包是一组执行单一任务的 .go 文件,每个文件顶部必须有 package 声明。模块将包分组,依赖关系固定在 go.mod 中。
库支持代码共享而无需重复。例如:将 MaxInt 函数复制到不同的包 foo 和 baz 中,如果没有单一来源,效率低下。包解决了编译和导入问题。
package foo
func MaxInt(a, b int) int {
if a > b {
return a
}
return b
}
组件隔离防止了解其他代码,分解简化了与编译器的交互。
库中的资源
库不仅包含代码,还包括外部资源:动态和静态。
动态资源 依赖于运行时。例如,通过 Gorgonia 的 cu 包访问 GPU:
d := cu.CurrentDevice()
ctx := cu.NewContext(d, cu.SchedAuto|cu.MapHost)
mem, err := ctx.MemAlloc(1024)
这里,ctx 是用于 GPGPU 任务的 GPU 描述符。其状态在编译时未知。
静态资源 是编译器已知的。例如,willshakes 包中的莎士比亚文本:
package willshakes
const AllsWellThatEndsWell = `第一幕 第一场
伯爵夫人。
在送走我儿子时,我埋葬了第二个丈夫。
...`
const MacBeth = `第一幕 第一场
第一女巫。
我们三个何时再相聚
...`
通过 willshakes.MacBeth 访问。类似地,字体或 MNIST 等数据集也是如此。
库的分类
库根据其资源分类:
- 代码库:包/模块中的共享源代码。
- 驱动库:驱动程序的包装器(如 CUDA 的 cu、OpenGL 的 go-gl)。
- 资源库:静态数据(如 willshakes)或加载器(如 Go 中的 mnist)。
| 类型 | 示例 | 特点 |
|------|---------|----------------|
| 代码 | 工具包 | 静态代码 |
| 驱动 | cu | 动态访问 |
| 资源 | willshakes | 嵌入常量 |
驱动程序为跨语言交互添加抽象层。
优秀库的品质
一个好的库促进两种对话:与机器(编译器/运行时)和与开发者。
标准:
- 隔离性:组件不了解外部库。
- 分解性:清晰的功能边界。
- 组合性:易于集成到应用程序中。
- 可预测性:行为符合文档描述。
- 性能:最小化开销,无妥协。
避免在库中使用 package main——专注于实用工具。测试边缘情况,确保线程安全。
关键要点
- 库是可共享的资源,不仅仅是代码仓库或包。
- 区分静态(常量)和动态(驱动程序)资源。
- 确保隔离,让开发者专注于单一任务。
- 使用 Go 包进行编译,模块管理依赖。
- 为组合设计:易于导入和使用。
— Editorial Team
暂无评论。