go-lib-design
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGo Library Design
Go库设计
Core Principles
核心原则
- Work backwards from usage. Write pseudo-code and documentation before implementation. Design the API you want callers to see, then build it.
- Minimize surface area. Smaller API = more internal freedom. When in doubt, leave it out. You can always export later; you can never unexport.
- Accept, don't instantiate. Take dependencies as arguments (preferably interfaces). Never instantiate what you don't own.
- Plan for growth. Signatures are frozen at v1.0. Use parameter objects, result objects, or functional options so APIs can evolve without breaking callers.
- 从使用场景倒推。 在实现前编写伪代码和文档。先设计你希望调用者看到的API,再进行构建。
- 最小化接口面。 更小的API意味着更多的内部自由度。拿不准的时候就不要对外暴露。你可以后续再导出,但一旦导出就无法撤销。
- 依赖注入,而非实例化。 将依赖作为参数传入(优先使用接口)。永远不要实例化你不拥有的对象。
- 为增长做规划。 签名在v1.0版本后即固定。使用参数对象、结果对象或函数式选项,让API在演进时不破坏现有调用者的代码。
Reference Index
参考索引
| Reference | Topics |
|---|---|
| design-process | Four design axes, work backwards, minimize surface area |
| surface-area | Internal packages, no global state, unknown outputs, mutation guards |
| dependencies | Accept don't instantiate, accept interfaces, return structs |
| evolution | Breaking changes, param objects vs functional options, result objects |
| testability | |
| 参考链接 | 主题 |
|---|---|
| design-process | 四个设计维度、从使用场景倒推、最小化接口面 |
| surface-area | 内部包、无全局状态、未知输出、变更防护 |
| dependencies | 依赖注入而非实例化、接受接口、返回结构体 |
| evolution | 破坏性变更、参数对象vs函数式选项、结果对象 |
| testability | |
When to Apply
适用场景
Apply when:
- Designing a new Go library or shared package
- Reviewing a library's public API before v1.0
- Deciding between functional options and parameter objects
- Auditing a package's export surface
Do NOT apply to application-level code that won't be imported by other modules.
适用场景:
- 设计新的Go库或共享包时
- 在v1.0版本前审查库的公共API时
- 在函数式选项与参数对象之间做抉择时
- 审计包的导出接口面时
不适用于不会被其他模块导入的应用级代码。
Quick Reference
快速参考
Design process: Write usage pseudo-code first. Optimize for usability, readability, flexibility, testability — in that order.
Surface area: Export only what you'll support forever. Use for non-public helpers. No global state — use struct methods.
internal/Dependencies: Accept , not . Accept interfaces, return structs. Provide convenience constructors () as wrappers.
io.Reader*os.FileNewFromFileEvolution: Cannot add params (use param objects), cannot add returns (use result objects), cannot add interface methods (use upcasting). Functional options for optional-only params with few required args; param objects when there are required fields or many options.
Naming: No — find the real noun. No // packages. Qualify short generic names with parent (, not ).
FooManagerutilcommonhelpershttptesttestDocs: Write for users, not maintainers. Don't bury the lede. Provide runnable examples. Keep a changelog separate from commit log.
Testability: Accept function type and via options with real defaults. Use for I/O. No global state. Deterministic output ordering. Match abstraction to need — function types over interfaces. Simulation is opt-in.
TimeNow*rand.RandWithXfs.FS设计流程:先编写使用场景的伪代码。按易用性、可读性、灵活性、可测试性的优先级进行优化。
接口面:仅导出你将永久支持的内容。使用目录存放非公共辅助代码。不要使用全局状态——使用结构体方法。
internal/依赖:接受而非。接受接口,返回结构体。提供便捷构造函数(如)作为封装。
io.Reader*os.FileNewFromFile演进:不能直接添加参数(使用参数对象),不能直接添加返回值(使用结果对象),不能直接添加接口方法(使用向上转型)。当必填参数少、可选参数多时使用函数式选项;当存在必填字段或大量选项时使用参数对象。
命名:不要使用这类名称——找到真正对应的名词。不要使用//这类包名。对简短的通用名称加上父级限定(如,而非)。
FooManagerutilcommonhelpershttptesttest文档:为用户而非维护者编写文档。不要隐藏关键信息。提供可运行的示例。将变更日志与提交日志分开存放。
可测试性:通过选项接受函数类型和,并提供真实默认值。使用处理I/O。不要使用全局状态。输出结果的顺序要确定。根据需求选择抽象方式——优先使用函数类型而非接口。模拟功能为可选启用。
WithXTimeNow*rand.Randfs.FS