Skip to content

Latest commit

 

History

History
58 lines (33 loc) · 7.9 KB

04.Names.md

File metadata and controls

58 lines (33 loc) · 7.9 KB

Names

Names are as important in Go as in any other language. They even have semantic effect: the visibility of a name outside a package is determined by whether its first character is upper case. It's therefore worth spending a little time talking about naming conventions in Go programs.

同其他编程语言一样,名称在 Go 语言中举足轻重,甚至具有语义上的影响:包内名称首字母的大小写会影响到其包外的可见性。因此,花费一点时间来讨论 Go 语言中的命名惯例是很有必要的。

Package names

When a package is imported, the package name becomes an accessor for the contents. After

import "bytes"

the importing package can talk about bytes.Buffer. It's helpful if everyone using the package can use the same name to refer to its contents, which implies that the package name should be good: short, concise, evocative. By convention, packages are given lower case, single-word names; there should be no need for underscores or mixedCaps. Err on the side of brevity, since everyone using your package will be typing that name. And don't worry about collisions a priori. The package name is only the default name for imports; it need not be unique across all source code, and in the rare case of a collision the importing package can choose a different name to use locally. In any case, confusion is rare because the file name in the import determines just which package is being used.

包被导入之后,其名称就成为包中内容的访问器。像 import "bytes" 这样导入 bytes 包之后,就可以使用类似 bytes.Buffer 的方式来访问包中内容了。如果每个使用包的人都采用同样的名称来引用包中内容的话,这无疑是一件大有裨益的事,但这意味着包应该有个合乎时宜的名字:短小精悍,简洁明了,且利于记诵。依照惯例,包名应该采用小写,单字;而且没有必要使用下划线或者混合大小写。一切皆从简,因为每个使用包的人都会输入这个名称。不要在理论上担心这会引起冲突。默认情况下,包在导入时其名称为访问器的名称,但并不是说包的名称要在整个源码中保持唯一;同时导入相同名称的包是非常罕见的,这种情况下我们可以局部地设置一个不一样的名称。不管怎样,导入文件的路径名决定了哪个包将被使用,故不致混淆。

Another convention is that the package name is the base name of its source directory; the package in src/encoding/base64 is imported as "encoding/base64" but has name base64, not encoding_base64 and not encodingBase64.

另一个惯例,包名是其源码目录的 basename; 例如 位于 src/encoding/base64目录中的包以 "encoding/base64" 的形式被导入,包名为 base64,而不是 encoding_base64,也不是 encodingBase64。

The importer of a package will use the name to refer to its contents, so exported names in the package can use that fact to avoid repetition. (Don't use the import . notation, which can simplify tests that must run outside the package they are testing, but should otherwise be avoided.) For instance, the buffered reader type in the bufio package is called Reader, not BufReader, because users see it as bufio.Reader, which is a clear, concise name. Moreover, because imported entities are always addressed with their package name, bufio.Reader does not conflict with io.Reader. Similarly, the function to make new instances of ring.Ring—which is the definition of a constructor in Go—would normally be called NewRing, but since Ring is the only type exported by the package, and since the package is called ring, it's called just New, which clients of the package see as ring.New. Use the package structure to help you choose good names.

导入者使用包的名称访问其内容,因此包中导出的名称可以利用这一点来避免一些重复。(不要使用import .,即便这会简化那些必须在包外运行的测试,不过,除此之外应避免使用)例如,bufio包中带缓冲的 reader 类型名为 Reader,而不是 BufReader,因为使用者将其视作 bufio.Reader,这无疑是一个清晰简洁的名字。此外,被导入者在使用时都会冠以包名,故 bufio.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. A helpful doc comment can often be more valuable than an extra long name.

另一个简短的例子是 once.Do ,once.Do(setup) 拥有很好的可读性,改为 once.DoOrWaitUntilDone(setup)并不会有所改善。较长的名字并不会提高可读性,一段有益的文档注释往往要比一个额外的冗长名称更具价值。

Getters

Go doesn't provide automatic support for getters and setters. There's nothing wrong with providing getters and setters yourself, and it's often appropriate to do so, but it's neither idiomatic nor necessary to put Get into the getter's name. If you have a field called owner (lower case, unexported), the getter method should be called Owner (upper case, exported), not GetOwner. The use of upper-case names for export provides the hook to discriminate the field from the method. A setter function, if needed, will likely be called SetOwner. Both names read well in practice:

Go 没有自动支持 gettersetter 。当然,你自己实现也没有什么不妥,通常情况下理应如此,但在 getter 的名字上加入 Get 既不地道也没必要。如果你有一个名为 owner 的字段(小写,未导出),那么 getter 应该命名为 Owner(大写,导出),而不是 GetOwner。使用大写名称向外暴露内容有助于我们辨别字段和方法。如果确实需要 setter 方法,尽可能命名为 SetOwner。实践证明,这种命名方式工作良好。

owner := obj.Owner()
if owner != user {
    obj.SetOwner(user)
}

Interface names

By convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun: Reader, Writer, Formatter, CloseNotifier etc.

按照惯例,仅有一个方法的接口要以方法名添加 -er 的后缀来命名,或者通过类似的修改来构造一个施动名词:Reader,Writer,Formatter,CloseNotifier 等等

There are a number of such names and it's productive to honor them and the function names they capture. Read, Write, Close, Flush, String and so on have canonical signatures and meanings. To avoid confusion, don't give your method one of those names unless it has the same signature and meaning. Conversely, if your type implements a method with the same meaning as a method on a well-known type, give it the same name and signature; call your string-converter method String not ToString.

有这么一些名字,它们已然被采用,具有公认的签名和意义,例如:Read, Write, Close, Flush, String 等等。对于这些名字,我们最好给予尊重,除非与其具有相同的签名和意义,否则不要使用,以避免造成混淆。反之,如果你的类型方法和知名类型的方法意思相同,此时当采取相同的方法签名;比如,字符串转换函数需命名为 String 而不是 ToString

MixedCaps

Finally, the convention in Go is to use MixedCaps or mixedCaps rather than underscores to write multiword names.

最后,Go 惯于采用驼峰法(CamelCase)书写多字名称,而不是蛇形法(snake_case)。