参考

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. lintcode_114_不同的路径

    不同的路径   描述 笔记 数据 评测 有一个机器人的位于一个 m × n 个网格左上角. 机器人每一时刻只能向下或者向右移动一步.机器人试图达到网格的右下角. 问有多少条不同的路径? 注意事项 n和 ...

  2. spring cloud 学习之服务消费者(rest+ribbon)

    学习自 http://blog.csdn.net/forezp/article/details/81040946 方志朋的博客 在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于h ...

  3. selenium webdriver 移动到某个位置,滚动到某个位置

    https://blog.csdn.net/xiaosongbk/article/details/70231564

  4. 还在使用pdf、word简历?简单五步实现github托管个人逼格简历

    写在前面: 什么是git.github? git 版本控制工具 github 通过git工具做的版本控制的项目托管平台 项目开发肯定不止一个程序猿,多个程序猿针对同一个文件进行代码读写操作时,是先保存 ...

  5. python__标准库 : 测试代码运行时间(timeit)

    用 timeit.Timer.timeit() 方法来测试代码的运行时间: from timeit import Timer def t1(): li = [] ): li.append(i) def ...

  6. SpringMVC文件上传——bean的配置【org.springframework.web.multipart.commons.CommonsMultipartResolver】

    一.简介 Spring MVC支持一个通用的多路上传解析器CommonsMultipartResolver,在Spring的配置文件中对CommonsMultipartResolver Bean进行配 ...

  7. 笔记-pyton内置数据类型

    笔记-pyton内置数据类型 1.      简介 The principal built-in types are numerics, sequences, mappings, classes, i ...

  8. Android 使用Retrofit2.0+OkHttp3.0实现缓存处理+Cookie持久化第三方库

    1.Retrofit+OkHttp的缓存机制 1.1.第一点 在响应请求之后在 data/data/<包名>/cache 下建立一个response 文件夹,保存缓存数据. 1.2.第二点 ...

  9. P2580 于是他错误的点名开始了(trie)

    P2580 于是他错误的点名开始了 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边搓炉石一边点名以至于有一天他连续点到了某个同学两次,然后正好被路过的校长发现了然后就是一顿欧拉欧拉欧拉 ...

  10. Win7更换锁屏和开机画面

    技术交流群:233513714 每次开机被Windows千年不变的开机画面和锁屏画面丑到的小伙伴们可以看过来,通过简单的几步就可以改掉系统默认的开机画面. 1.首先Windows+r键输入regedi ...