5.4. 命名

名称在 Go 里和在其它语言里一样重要。某种情况下它们甚至有语义效果:例如,一个名称能否在包外可见取决于它的第一个字母是否大写。所以值得花点时间探讨下 Go 程序的命名约定:

5.4.1. 包的命名

当包引入时,包名成为其内容的引导符。

import "bytes"

后, 导入者可以讲 bytes.Buffer。更有用的是每个包的用户都能使用相同的名称指出它的内容,亦即包应有个好名称:短,精,好记。习惯上包名是小写的单字的名称;应无必要用下划线或大小混写。简错不纠,因为你的包的每个用户都要敲这个名字。还有不要无谓烦扰撞名。包名只是引入时的默认名;它不需在所有源码中都唯一,如出现少见的撞名,导入者可以给出不同的名字局部使用。无论如何,撞名很少见,因为 import 用的文件名只决定使用那个包。

另一个习惯是包名是源目录的基名;src/pkg/container/vector 里的包引入为 “container/vector” 但包名是 vector,不是 container_vector 也不是 containerVector。

导入者使用包名引导其内容 (import . 的记法主要特意用在测试或其它不寻常的场合),所以包的导出的名称可据此避免结结巴巴。例如,bu?o 包的 buffered reader 叫 Reader,不叫 BufReader,因为用户看到的是 bu?o.Reader 这个清楚简短的名称。再有,因为导入项总是给出其包名,bu?o.Reader 不会和 io.Reader 撞名。类似的,用来生成 ring.Ring 的函数 — 即 Go 的架构函数 — 通常会被称为NewRing,但因为 Ring 是此包唯一的导出类型,并且既然包名叫ring,它就叫 New。此包的客户看到的是 ring.New。使用包结构帮你来选个好名。

Another short example is once.Do; once.Do(setup) reads well and would not be improved by writing once.DoOrWaitUntilDone(setup). Long names don't automatically make things more readable. If the name represents something intricate or subtle, it's usually better to write a helpful doc comment than to attempt to put all the information into the name.

5.4.2. 接口的命名

习惯上,单一成员的界面的名称是其成员名加 -er:Reader, Writer,Formatter 等。

存在这样的一些名称,尊重它们和它们所指的函数会工作的更好。Read, Write, Close, Flush, String 等保有正统的签名和意义。为了避免混淆, 除非有同样的签名和意义,不要给你的方法这些名字。同理,如果你的方法实现了和这些著名方法同样的意图,给它同样的名称和签名;叫你的字符转换器 String 而不是 ToString。

5.4.3. 大小写混写

最后,Go 习惯使用 MixedCaps 和 mixedCaps,而不是下划线来写多字的名称。