写点什么

翻译: Effective Go (1)

用户头像
申屠鹏会
关注
发布于: 2020 年 04 月 22 日

介绍

Go 是一门新的编程语言。尽管它继承了一些现有语言的思想,但它独特的特性可以编写与其他语言截然不同的高效程序。将 C++或 Java 程序直接转换成 Go 程序并不会令人满意——Java 程序是 Java 写的,并不是用 Go。另一方面,从 Go 的角度去考虑问题,可能会产生(与 Java 相比)非常不一样的程序。换句话说,要想会写 Go,就要了解语言的特性和惯用用法。了解例如命名,格式化,程序构造之类的约定也同样重要,这样编写的 Go 程序才易于其他 Go 程序员理解。

本文档提供了编写清晰,惯用的 Go 代码的技巧。它拓展了语言的规范,建议先阅读 A Tour of Go 和[How to Write Go Code](https://xabc.site/post/trahowtowritego/)

示例

Go 软件包的源代码不仅是一个核心库,同时也是如何使用 Go 语言的示例源码。此外,很多软件包还包含了可以运行、自包含的可执行示例,可以直接在 golang.org(需要科学上网,如图 1)网站上运行。例如本示例(译者注:方便起见,直接复制代码到下文了).

package main
import ( "fmt" "strings")
func main() { rot13 := func(r rune) rune { switch { case r >= 'A' && r <= 'Z': return 'A' + (r-'A'+13)%26 case r >= 'a' && r <= 'z': return 'a' + (r-'a'+13)%26 } return r } fmt.Println(strings.Map(rot13, "'Twas brillig and the slithy gopher..."))}
复制代码

如果读者对如何解决问题或某些东西如何显示有疑问,也可以从软件包中的文档,代码和示例中获得答案,想法和背景。


格式

格式问题是最有争议但其实后果最不严重的问题。人们虽然可以适应不同的格式化风格,但是如果他们不必这么做其实是更好的一种选择,如果每个人都遵循相同的风格,那么浪费在格式风格上的时间就很少。问题就在于如何在没有冗长格式风格说明指南的情况下达到这种“乌托邦式”的理想情况。

使用 GO 时,我们独辟蹊径,让机器处理绝大多数格式化问题gofmt 程序(也可以作为 go fmt使用,它在包级别而不是源文件级别运行)读取 Go 程序,以缩进和垂直对齐的标准样式处理源代码,并保留注释,如果有必要,则重新格式化注释。如果读者想知道如何处理一些新的布局情况,请运行 gofmt;如果结果看起来不正确,请调整自己的程序(或者提交一个 gofmt 的 bug),不要纠结。

例如,无需花时间将结构体字段上的注释进行排列,Gofmt 会做到这一点。比如:

type T struct {    name string // name of the object    value int // its value}
复制代码

gofmt 会重新格式化成:

type T struct {    name    string // name of the object    value   int    // its value}
复制代码

标准软件包中的所有 Go 代码均已使用 gofmt 格式化。

有一些保留的格式细节,非常简要:

  • 缩进

除非自己必须使用空格,我们默认使用 Tab 缩进。

  • 单行长度

Go 没有单行长度限制。如果单行感觉太长,可以用 tab 进行包裹缩进。

  • 括号

Go 需要的括号比 C 和 Java 少:控制结构(if, for, switch)在语法上没有括号。 而且,运算符优先级层次更短更清晰,比如:x<<8 + y<<16。与其他语言不同,空格可以很容易知道它的用意。

注释

Go 提供了 C 语言的块注释样式:/ * * /和 C++的行注释样式//。通常使用行注释,而块注释主要用于包,或者用于禁用大段代码。

godoc既是一个程序,也是一个 Web 服务器,它对 Go 源文件进行处理,提取包内容。在顶级声明之前出现的注释(没有中间的换行符)与声明一起被提取,以用作该项目的说明文档。这些注释的类型和样式决定了 godoc 生成的文档质量。

每个包都应在包声明之前有一个块注释作为整个包的注释。对于多文件包,包注释仅需要出现在一个任意的文件中。包注释应介绍包,并提供与包整体有关的信息。它会首先出现在 godoc 页面上,并为紧随其后的内容建立详细的文档说明。

/Package regexp implements a simple library for regular expressions.
The syntax of the regular expressions accepted is:
regexp: concatenation { '|' concatenation } concatenation: { closure } closure: term [ '' | '+' | '?' ] term: '^' '$' '.' character '[' [ '^' ] character-ranges ']' '(' regexp ')'*/package regexp
复制代码

如果包比较简单,包的注释可以很简要:

// Package path implements utility routines for// manipulating slash-separated filename paths.
复制代码

注释不需要额外的格式,例如星号横幅。生成的输出甚至不会以固定宽度的字体显示,因此不必依赖对齐间距——godoc 会处理这些问题。注释是不会被解析的纯文本,因此 HTML 和其他注释,例如 this 将被原样输出,所以不应使用。godoc 所调整就是以固定宽度的字体显示已经缩进的文本,来适用程序片段。fmt 软件包的包注释使用此方法获得了不错的效果。

根据上下文的不同,godoc 可能甚至不会重新格式化注释,因此需要确保他们看起来非常清晰:使用正确的拼写,标点和句子结构,折叠长行等。

在包内部,顶级声明之前的任何注释都将用作该声明的 doc 注释。程序中每个导出的(首字母大写的)名字都应该带有文档注释。

文档注释最好作为完整的句子使用,这样才能适应各种自动化的展示。第一句应为单句摘要,并以声明的名称开头。

// Compile parses a regular expression and returns, if successful,// a Regexp that can be used to match against text.func Compile(str string) (*Regexp, error) {
复制代码

如果每个 doc 注释以条目所描述的项目名称开头,那么就可以使用go doc命令,通过 grep 查找输出。假如你需要寻找正则表达式的解析(单词:parse)函数,但是忘记了"Compile"的函数名称,你就可以运行命令:

$ go doc -all regexp | grep -i parse

若包中的所有文档注释都以"This function..."开头,grep就不能帮你想起这个函数。但是因为包以每个文档注释的名称开头,你就可以看到以下的内容,它就会帮你回想起想找的单词:

$ go doc -all regexp | grep -i parse    Compile parses a regular expression and returns, if successful, a Regexp    MustCompile is like Compile but panics if the expression cannot be parsed.    parsed. It simplifies safe initialization of global variables holding$
复制代码

Go 的声明语法允许对声明进行分组。单个文档注释可以引入一组相关的常量或者变量。由于是整体声明,这种注释比较简单。

// Error codes returned by failures to parse an expression.var (    ErrInternal      = errors.New("regexp: internal error")    ErrUnmatchedLpar = errors.New("regexp: unmatched '('")    ErrUnmatchedRpar = errors.New("regexp: unmatched ')'")    ...)
复制代码

分组还可以表明项目之间的关系,比如某一组由互斥锁保护的变量。

var (    countLock   sync.Mutex    inputCount  uint32    outputCount uint32    errorCount  uint32)
复制代码

原文链接:https://xabc.site/post/tra_effective_go/

发布于: 2020 年 04 月 22 日阅读数: 62
用户头像

申屠鹏会

关注

enjoy~ 2018.11.08 加入

https://xabc.site

评论

发布
暂无评论
翻译: Effective Go (1)