gopl-zh.github.com/ch10/ch10-06.md

47 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

## 10.6. 包和命名
在本节中我们将提供一些关于Go语言独特的包和成员命名的约定。
当创建一个包一般要用短小的包名但也不能太短导致难以理解。标准库中最常用的包有bufio、bytes、flag、fmt、http、io、json、os、sort、sync和time等包。
尽可能让命名有描述性且无歧义。例如类似imageutil或ioutilis的工具包命名已经足够简洁了就无须再命名为util了。要尽量避免包名使用可能被经常用于局部变量的名字这样可能导致用户重命名导入包例如前面看到的path包。
包名一般采用单数的形式。标准库的bytes、errors和strings使用了复数形式这是为了避免和预定义的类型冲突同样还有go/types是为了避免和type关键字冲突。
要避免包名有其它的含义。例如2.5节中我们的温度转换包最初使用了temp包名虽然并没有持续多久。但这是一个糟糕的尝试因为temp几乎是临时变量的同义词。然后我们有一段时间使用了temperature作为包名显然名字并没有表达包的真实用途。最后我们改成了和strconv标准包类似的tempconv包名这个名字比之前的就好多了。
现在让我们看看如何命名包的成员。由于是通过包的导入名字引入包里面的成员例如fmt.Println同时包含了包名和成员名信息。因此我们一般并不需要关注Println的具体内容因为fmt包名已经包含了这个信息。当设计一个包的时候需要考虑包名和成员名两个部分如何很好地配合。下面有一些例子
```
bytes.Equal flag.Int http.Get json.Marshal
```
我们可以看到一些常用的命名模式。strings包提供了和字符串相关的诸多操作
```Go
package strings
func Index(needle, haystack string) int
type Replacer struct{ /* ... */ }
func NewReplacer(oldnew ...string) *Replacer
type Reader struct{ /* ... */ }
func NewReader(s string) *Reader
```
包名strings并没有出现在任何成员名字中。因为用户会这样引用这些成员strings.Index、strings.Replacer等。
其它一些包可能只描述了单一的数据类型例如html/template和math/rand等只暴露一个主要的数据结构和与它相关的方法还有一个以New命名的函数用于创建实例。
```Go
package rand // "math/rand"
type Rand struct{ /* ... */ }
func New(source Source) *Rand
```
这可能导致一些名字重复例如template.Template或rand.Rand这就是这些种类的包名往往特别短的原因之一。
在另一个极端还有像net/http包那样含有非常多的名字和种类不多的数据类型因为它们都是要执行一个复杂的复合任务。尽管有将近二十种类型和更多的函数但是包中最重要的成员名字却是简单明了的Get、Post、Handle、Error、Client、Server等。