参考

Effective Go 官方文档

其他参考译文

https://studygolang.com/articles/3228

http://docscn.studygolang.com/doc/effective_go.html

Intruction

Go是一门新语言。尽管它也借鉴了现存语言的一些思想,使用GO完成一个高效(优秀)的程序,相比使用其他类似语言差异巨大。

直接将C++或Java翻译成Go是写不出好程序的(unlikely to produce a satisfactory result) ----Java程序就要用Java写,不能用Go。

Think about the problem from Go perspective could produce a succcessful but quite different program.

以Go的视角思考程序,会产生与从不同的优秀设计。

换种说法,要想写好Go程序,理解Go的特性和习惯十分重要。

It's also important to know the established conventions for programming in Go,

另外,了解Go程序的构建习惯也很重要,像命名,格式化,组织结构等等,规例这些标准的程序,其他Go开发者才更容易理解。

本文档描述如何编写清晰,符合惯例的Go代码技巧。

It augments the language specification, the Tour of Go, and How to Write Go Code, all of which you should read first.

此读此文档之前,最好先看看 语言规划,Go手册,如何编写Go代码几个文档。

Examples

Go package sources 不仅是核心库代码,也是演示如何Go语言的代码样例。此外,其中许多package是自包含且可执行的示例,

你能直接在 golang.org 网站中运行。

如果你有类似 “如何解决某问题” 或者 “如何实现某功能” 的疑问,也许能在这此文档、代码和示例找到答案或一丝线索。

Formatting

Formatting issues are the most contentious but the least consequential.

代码格式化(排版)也许是争议最多,但最不重要的问题了。

People can adapt to different formatting styles but it's better if they don't have to, and less time is devoted to the topic if every one adheres to the same style.

人们能适应不同的格式化风格,但如果所有人都坚持一种网络,就能在此类争议中节省更多时间

The problem is how to approach this Utopia without a long prescriptive style guide.

问题是,如何能在脱离冗长的代码风格指南的情况下,达到这种理想乌托邦呢。

在Go中,我们用了一种不同寻常的办法,那就是让机器解决大部分格式化问题。 gofmt 程序(即 go fmt命令,which operate at the package level rather than source file level)用于读取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格式化过。

还剩一些格式化要求,简介如下:

  • Indentation 缩进

    我们使用 tabs 缩进,gofmt默认也这样。非特殊情况,不要使用空格缩进
  • Line length 行长度

    Go不限制每行代码的长度。Don't worry overflowing a punched card. 不要担心穿孔卡片宽度不够(最早编程用穿孔卡片)。

    如果觉得一行太长了,就换行,然后用几个 tabs 缩进一下就行。
  • Parentheses 圆括号

    Go相比C和Java很少使用圆括号,控制结构(如 if, for, switch)的语法中都不要求圆括号。

    运算符的优先级别也更简洁清晰,比如:
x<<8 + y<<16

表示含义同空格分隔的一样,不像其他语言那么麻烦(TODO验证其他语言有什么问题?)

Commentary 注释

Go提供C风格的块注释/* */,还有C++风格的行注释//。行注释使用更普遍一些,块注释较多用于package注释中,

另外也用于行内注释,或者注释某一大段代码块。(行内注释即: if a>b /&& a>c/ ,其中 a>c的条件就失效了 )

godoc命令用于提取Go源代码中的注释。

Comments that appear before top-level declarations. with no intervening newlines, are extracted along with the declaration to serve as explanatory text for the item. The nature and style of these comments determines the quality of the documentation godoc produces.

每个紧挨 package 声名(clause) 的块注释中,都该有package说明注释(comments)。对于含有多个文件的package,说明应该集中在一个文件中(任意一个文件都可以)。

package的说明应该包含自己简介,及所有相关信息。

这些注释会出现在 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 很简单,package 注释也可以简略一点。

// Package path implements utility routines for
// manipulating slash-separated filename paths.

说明(comments)文字本身不需要格式化(如banners of starts)。godoc输出的文档是非等宽字体,

所以不能像gofmt那样依赖空格对齐。

The comments are uninterpreted plain text, so HTML and other annotations such as this will reproduce verbatim and should not be used. One adjustment godoc does do is to display indented text in a fixed-width font, suitable for program snippets. The package comment for the fmt package uses this to good effect.

说明文字是不经过处理的文本,所以类似 HTML 或者 this 一类的符号会直接显示,尽量不要使用。

但 godoc 会使用等宽字体显示缩进过的文本,用来放置代码片段。标准库中 fmt 就使用了类似效果。

Depending on the context, godoc might not even reformat comments, so make sure they look good straight up: use correct spelling, punctuation, and sentence structure, fold long lines, and so on.

根据实际情况, godoc 也许不会改动说明的格式,一定确保拼写、标点、句子结构以及换行都没有问题。

package内部,所有紧挨声明之上的注释文字,都被当做文档。所有导出变量(大写字母开头)都会生成文档。

Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.

文档说明最好是一个完整句子,这样方便任意显示格式。注释的第一句话,应该以所声名的变量名称开头,做简要介绍。

// 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) {

如果每个文档说明都以它描述的变量名开头,godoc 的输出与 grep 配合使用会很方便。

假设你想寻找正则表达式函数,但不记得函数名是"Compile"了,你可以使用下面的命令搜索文档。

$ godoc regexp | grep -i parse

如果文档说明没有以它描述的函数名开关(即"Compile"),grep 就没法显示出准确的函数名。

但我们要求每个package中的文档注释都以它描述的变量名开头,你就能看到类似下面的输出结果:

$ godoc regexp | grep parse
Compile parses a regular expression and returns, if successful, a Regexp
parsed. It simplifies safe initialization of global variables holding
cannot be parsed. It simplifies safe initialization of global variables
$
// TODO 在 windows 7 go 1.9.1 中测试,godoc 输出的函数文档虽然逻辑上是一句话
// 但实际输出仍然是多行的,所以 grep 过滤时,不会显示 Compile 这行字符
// 这也就达不到上文说的目的了,不知道是不是我测试环境有问题?

Go's declaration syntax allows grouping of declarations. A single doc comment can introduce a group of related constants or variables. Since the whole declaration is presented, such a comment can often be perfunctory.

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 ')'")
...
)

批量声名通常指明几个相关数据项,比如下面这种,多个变量同时由一个mutex保护。

var (
countLock sync.Mutex
inputCount uint32
outputCount uint32
errorCount uint32
)

Names

Go语言中命名的重要性同其他语言一样。命名甚至能影响语法:package中变量名称首字母大小写决定其是否对外部可见。

因此值我们花点时间了解有关Go的命名习惯。

Package Names

当 package 导入(import)时,其 package name 就是一个访生问器。出现下面代码后,

import "bytes"

我们就能使用 bytes.Buffer 这样的类型了。每个使用 package 的人都能用相同的 name 引用package,

就说明这是一个具备这些特点的好的名称:短、简洁、形象 (vocative) 。

packages 一般使用小字的单个单词命名,不加下划线或者大小写字母。

Err on the side of brevity, since everyone using your package will be typing that name.

不用担心冲突(collisions a priori)。 package name 只是import时的默认名称;没必要在所有源代码中都是唯一的。

偶尔遇到冲突时,使用局部重命名就能解决。而且import的名称只决定被使用的package。(In any case, confusion is rare because the file name in the import determines just which package is being used.)

另外一个惯例是,package 名称是源代码所有目录的名称;

比如 src/encoding/base64 导入时使用 import "encoding/base64" ,但真正调用时,使用"base64"作为名称。

既不是encoding_base64,也不是encodingBase64

使用者通过 package name 引用 package 中的内容,so exported names in the package can use that fact to avoid stutter.

(Don't use the import . notation, which can simplify tests that must run outside the package they are testing, but should otherwise be avoided.)

比如在bufio中的 buffered reader 的 package name 是Reader,而不是BufReader,因为使用者通过 bufio.Reader 调用。

因为调用者总会加上 package name 为前缀使用,所以 bufio.Reader 永远不会和 io.Reader 冲突。

同样,一般用于创建一个ring.Ring的新实例的函数,我们起名为NewRing,但因为Ring中 package ring 中的导出类型,

所以我们将函数命名为New就可以了。这样用户就能使用ring.New这种简洁的名称。

利用 package 的目录结构帮你起个好名字。(Use the package structure to help you choose good names.)

还有个例子,once.Do; once.Do(setup)明显就比once.DoOrWaitUntilDone(setup)好多了。

过长的名字反而可能影响可读性。好的 doc comment 可能比冗长的名称要有用得多。

(译:结论我同意,但这个例子中,我觉得 DoOrWaitUntilDone() 更好,还不到20个字符的名字,不能算长

golang effective 翻译的更多相关文章

  1. Go的50度灰:Golang新开发者要注意的陷阱和常见错误(转)

    目录 [−] 初级 开大括号不能放在单独的一行 未使用的变量 未使用的Imports 简式的变量声明仅可以在函数内部使用 使用简式声明重复声明变量 偶然的变量隐藏Accidental Variable ...

  2. [转载]Go的50度灰:Golang新开发者要注意的陷阱和常见错误

    初级 开大括号不能放在单独的一行 未使用的变量 未使用的Imports 简式的变量声明仅可以在函数内部使用 使用简式声明重复声明变量 偶然的变量隐藏Accidental Variable Shadow ...

  3. Golang新开发者要注意的陷阱和常见错误

    转自:http://colobu.com/2015/09/07/gotchas-and-common-mistakes-in-go-golang/ 目录 [−] 初级 开大括号不能放在单独的一行 未使 ...

  4. GO 新开发者要注意的陷阱和常见错误

    转自:http://colobu.com/2015/09/07/gotchas-and-common-mistakes-in-go-golang/ 初级 开大括号不能放在单独的一行 未使用的变量 未使 ...

  5. Effective Modern C++翻译(1):序言

    /*********************************************************** 关于书: 书是我从网上找到的effective Modern C++的样章,内 ...

  6. 《Effective Modern C++》翻译--简单介绍

    北京时间2016年1月9日10:31:06.正式開始翻译.水平有限,各位看官若有觉得不妥之处,请批评指正. 之前已经有人翻译了前几个条目,有些借鉴出处:http://www.cnblogs.com/m ...

  7. <More Effective C#: 改善C#代码的50个有效方法>中文版翻译答疑

    最近, 有一本很赞的.NET技术书中文版出版了 - <More Effective C#: 改善C#代码的50个有效方法>.    从广州\西安\长沙\上海等各地.NET俱乐部都收到反馈, ...

  8. Golang+Protobuf+PixieJS 开发 Web 多人在线射击游戏(原创翻译)

    简介 Superstellar 是一款开源的多人 Web 太空游戏,非常适合入门 Golang 游戏服务器开发. 规则很简单:摧毁移动的物体,不要被其他玩家和小行星杀死.你拥有两种资源 - 生命值(h ...

  9. 翻译下 golang package time

    # 关于 `package time` 个人体会:"wall clock" 可以理解为就是实际的时钟,而 "monotonic clock" 则是程序内部的时钟 ...

随机推荐

  1. HDU.2111 Saving HDU(贪心)

    题目来源:Saving HDU 题意分析: XHD有个容量为v的口袋,有n个宝贝,每种宝贝的价值不一样,每种宝贝单位体积的价格也不一样,宝贝可以分割,分割后的价值和对应的体积成正比.求XHD最多能取回 ...

  2. lintcode_115_不同的路径 II

    不同的路径 II   描述 笔记 数据 评测 "不同的路径" 的跟进问题: 现在考虑网格中有障碍物,那样将会有多少条不同的路径? 网格中的障碍和空位置分别用 1 和 0 来表示. ...

  3. asciinema使用

    asciinema让您轻松记录终端会话,并在终端和网页浏览器中重播它们. 安装最新版本: sapt-get install asciinema 记录你的第一个终端视频: asciinema rec f ...

  4. JAVA / MySql 编程——第七章 JDBC

    1.JDBC:JDBA是Java数据库连接(Java DataBase Connectivity)技术的简称,提供连接各种常用数据库的能力:         ●Java是通过JDBC技术实现对各种数据 ...

  5. Centos6.8安装python3.6

    1.目的简介: centos默认使用的是python 2.6.6,而python的2.x 和 3.x 是两个不兼容的版本,到目前的python发展,都已经过渡到了python 3.x,所以需要手动将p ...

  6. php-5.6.26源代码 - opcode执行

    文件 php-5.6.26/Zend/zend_vm_execute.h ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS ...

  7. php面向对象(2)值传递

    PHP中值传递方式,2中 值传递:传递的时候,拷贝的是数据本身.默认都是值传递 结果:传递完成,有了2份同样的数据,且2个变量“相互独立”,不会相互影响 引用传递:传递的时候,拷贝的是引用关系(数据的 ...

  8. Nginx 高级配置

    nginx官方网站:http://nginx.org/ 1.  Nginx连接后端的方式:反向代理(proxy_pass).直连fastcgi(fastcgi_pass) 例子: fastcgi_pa ...

  9. gradle编译很慢解决方法

    1.升级内存,内存最好在8g以上. 我的12g,编译运行,2s22ms,不到3s. 2.设置Android staido 不要 打开instant run

  10. Redis数据更新

    技术交流群: 233513714