名字
就像其他语言一样,名字在Go语言中也是很重要的。它甚至有语义的效果:从包外访问一个变量取决于它的首字母是否大写。因此花费一点时间探讨Go语言中的命名问题是值得的。
包名
当一个包被导入,程序包名便可以用来访问它的内容。在
import "bytes"
之后,当前的包便可以使用bytes.Buffer。如果每一个人在使用程序包的时候可以使用相同的名字来引用它的内容将会是很有帮助的。这意味着程序包名要很好:简短、简洁、能引起共鸣的。根据约定,包名使用小写的一个单词来命名。其中不需要使用下划线或者驼峰法。要力求简短,因为每一个使用你的包的人都会敲一遍名字。不用担心和之前的命名冲突。包名只是导入的默认的名字。它不需要在所有的源代码中都是唯一的。在很少的冲突情况下,导入的包可以选择一个在本地使用的不同的名字。不管怎样,出现冲突是很稀少的,因为导入的文件名决定了哪一个包将被使用。
另一个约定是,包名是它的源目录的基础名。例如在src/encodeing/base64中的程序包将会作为encodeing/base64导入,但是名字是base64,不是encodeing_base64,也不是encodeingBase64。
程序包的导入者将会使用包名来引用变量。所以导入的包的名字可以用来避免口吃现象。(不要使用import .标记,这将简化哪些本应该运行在包外,但不应该被避免的测试。);例如,缓存阅读器类型在bufio包中被称为Reader,而不是BufReader。因为用户把它看做bufio.Reader,这是一个清楚、简洁的名字,bufio.Reader不会和io.Reader产生冲突。类似地,构造新实例ring.Ring的函数——作为Go中构造函数的定义——通常被叫做NewRing,但是因为Ring是包中唯一的导出类型,并且包名被称作ring,它就只叫做New。这样程序包的客户就会看到ring.New。用包结构能帮助你选择好的名字。
另一个简短的例子是once.Do;once.Do(setup)可读性很好,而写成once.DoOrWaitUntilDone(setup)并不会有太大的提高。长名字并不会自动让事物变得好读。具有帮助性的文档注释通常比格外长的名字更有用。
Getters
Go并不会对getter和setter方法提供自动的支持。但你自己来写getter和setter方法也没有什么不好的,而且这么做通常也是合理的。但是这既不地道也没必要把Get放进getter方法里。如果你有一个字段owner(小写未导出),它的getter方法应该是Owner(大写,导出),而不是GetOwner。大写字母的名字用于导出的用法提供了从方法中区别字段的钩子。在有必要的情况下,一个setter方法也可以叫做SetOwner.这些名字实际都很好读。
owner := obj.Owner()
if owner != user {
obj.SetOwner(user)
}
接口名
按照约定,一个方法的接口由方法名加上-er后缀命名,或者类似的修改来构造一个代理名词,例如:Reader、Writer、Formatter、CloseNotifier等。
有很多这样的名字,最有效的方式是尊重它们,以及它们所体现的函数名。Read、Write、Close、Flush、String等都有规范的标志和含义。为了避免混淆,不要给你的函数取其中的名字,除非它有着相同的标志和含义。反过来说,如果你的类型实现了一个于众所周知的类型有着相同含义的方法,那么就使用相同的方法和签名。调用你的字符串转换方法String而不是ToString.
混合大小写
最后,Go中的一条约定是使用MixedCaps或者mixedCaps的格式来写复合单词的名字而不是使用下划线。