不该以类型来给 Go 的变量命名,就如你不该将你家的猫取名为猫一样
变量名应描述其内容,而不是内容的 type(类型)。考虑以下示例:
var usersMap map[string]*User
此声明有哪些好的属性? 我们可以看出它是一个 map (映射),并且与 *User
类型有关,所以这可能很好。但是 usersMap
是 一个映射,Go 作为一种静态类型语言,不会让我们意外地使用需要不同类型的映射,因此 Map
后缀作为安全预防措施是多余的。
现在,考虑一下如果我们使用此模式声明其他变量会发生什么:
var (
companiesMap map[string]*Company
productsMap map[string]*Products
)
现在,我们在作用域中有三个映射类型的变量,usersMap
、compiesMap
和 productsMap
,它们都将 string
映射到各自不同的 struct
类型。我们知道它们是映射,并且我们也知道它们的声明是为阻止我们使用一个映射来代替另一个 —— 如果我们在需要 companiesMap
的地方尝试使用 map[string]*User
,编译器将抛出一个错误。在这种情况下,很明显 Map
后缀并不能提高代码的清晰度,它只是一个额外的输入样板。
这个建议也适用于函数参数。例如:
type Config struct {
//
}
func WriteConfig(w io.Writer, config *Config)
将 *Config
参数命名为 config
是多余的。我们知道它是一个指向 Config
的指针,它在声明中就这样说了。相反,如果变量的生存期足够短,请考虑 conf
是否可以使用,或者仅仅 c
即可。
这个建议不仅仅是对简洁的渴望。如果在任何同一时间一个作用域内有一个以上的 *Config
,则将它们称为 config1
和 config2
要比将它们称为 original
和 updated
的描述性小得多。后者不太可能被意外调换 —— 这是编译器无法捕获的,而前者只在一个字符后缀上有所不同。
最后,不要让包名窃取好的变量名。导入的标识符的名称包括其包名称。例如,当导入到另一个包中时,Context
包中的 context
类型将被称为 context.Context
。这使它不可能使用 context
作为变量或类型,当然除非您重命名导入,但这会一反常态。这就是为什么 context.Context
类型的本地声明传统上是ctx
的原因。例如
func WriteLog(ctx context.Context, message string)
变量的名称应该独立于其类型。不应该用变量类型来命名变量,就像你不会将宠物取名为「狗」或者「猫」一样。所以出于相同的原因,不应该在变量名称中包含变量类型。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: