Tip #34 以context开头,以options结尾,并且总是用error来关闭

原始链接:Golang Tips #34: Lead with context, end with options, and always close with an error

编写符合习惯的Go代码通常涉及遵循一定的模式和最佳实践,这些模式和实践能够提升代码的可预测性。

这里是3个设计函数签名时的关键准则:

1. context.Context放在前面

在函数签名中,context.Context 应当始终放在首位。

“为什么?”

context 通常与一个请求或者操作的生命周期息息相关。

当浏览代码时,一看到 context.Context 作为第一个参数,就立刻让人明白这个函数有如下的特性:

  • 取消
  • 截止期限
  • 其他上下文相关的机制

这种一致性有助于提高代码的可读性,并且让代码库变得易于浏览。

此外,别把context.Context放到 struct 中。

context 本质上意味着它注定是短暂的,旨在贯穿于一段程序,而非成为对象状态的一部分(这里有一些例外情况,比如,HTTP 的 handler,大家习惯地从请求中提取 context,这是因为 context 早已跟请求的生命周期相关联了)。

2. Options结构体置于最后

“options结构体”模式是一个灵活而强大的方法,它能让函数在不破坏兼容性的前提下随着时间去演进。

我曾在推特上探讨过 options 结构体和可变参 options:twitter.com/func25/status/...

参数的顺序可能表明了这个参数的重要性。

把这个结构体作为一个函数的最后一个参数有两个目的:

  • 保持一致性(与可变参 options 模式一致)
  • 表明这些是可选配置项,而非函数操作逻辑的核心部分

3. 以error(或者bool)结尾

Go习惯通过最后一个返回值(通常是一个error)来表明一个操作是成功还是失败。

某些情况中,如果布尔值更加妥当,比如说存在性检查,那么它也是放到最后的。

如果兼而有之,那么优先级应当是(x, bool, error)。

在譬如 TryFetchData 的场景中,bool 被用来表明存在性,特别是即便不存在也不会被当做是一个错误。