一 格式化

使用gofmt程序对go源码进行格式化,以便统一编码风格,可直接在GoLand进行配置[1]。Go源码格式使用tab作为缩进,且很少使用括号。

二 注释

Go支持块注释/**/和行注释//,行注释更常用,块注释主要用于包注释和大块代码禁用。godoc[2]支持从注释中提取文档,每个包和可导出的名称(大写)都应该提供注释。包注释对包整体进行介绍,并提供相关的信息,模版示例如图2.1:

图2.1 包注释

文档注释应该是一个以声明的名称开始的完整的句子,如图2.2:

图2.2 文档注释

go支持变量成组声明,对于一组相关的变量或常量,文档注释应该给出笼统的介绍,如图2.3:

图2.3 相关常量注释

三 命名

3.1 包名

包应以单个小写单词命名,且不该使用下划线和驼峰记法。
包名应是源码目录的基本名称,例如: 在 src/pkg/encoding/base64 中的包应作为 "encoding/base64" 导入,其包名应为 base64

3.2 Getters

获取器名字中无需加入Get,例如owner字段的获取方法为Owner(),设置器为SetOwner(),如图3.1:

图3.1 Getters

3.3 接口名

只包含一个方法的接口,接口名应为方法名加类似er后缀的名词,比如Reader, Writer, Formatter, CloseNotifier。
Read、Write、Close、Flush、 String等具有典型签名和意义的方法,除非明确方法名称和这些典型的方法具有相同的签名和含义,否则不要用这些名称(具有相同签名和意义时要用这些名称)。

3.4 驼峰记法

Go约定命名使用驼峰记法MixedCaps 或 mixedCaps。

四 分号

Go词法分析会在源码中插入分号,插入分号规则如下:
若在新行前的最后一个标记为标识符(包括 int 和 float64 这类的单词)、数值、字符串常量或break continue fallthrough return ++ -- ) }等标记之一(如果新行前的标记为语句的末尾,则插入分号)。
控制结构左大括号不应放在下一行,会导致在大括号前面加分号。


图4.1 控制结构错误示例

五 控制结构

Go与C控制结构不同之处:Go循环只有for语句;if和switch可像for循环接受可选的初始化语句;包含类型选择和多路通信复用器结构:select;语法上,没有圆括号,而其主体必须始终使用大括号括住。

5.1 重新声明与再次赋值

经常发现变量err会多次:=声明,其本质是再次赋值, 在满足下列条件时,已被声明的变量 v 可出现在:= 声明中:
1. 本次声明与已声明的 v 处于同一作用域中(若 v 已在外层作用域中声明过,则此次声明会创建一个新的变量)。
2. 在初始化中与其类型相应的值才能赋予 v,且在此次声明中至少另有一个变量是新声明的。

5.2 switch

若switch后无表达式,它将自动匹配true执行,因此可以将if-else-if-else链写成switch的方式,如图5.1所示。

图5.1 无表达式switch

case可通过逗号分隔列举相同的处理条件,如图5.2:

图5.2 相同处理case

可使用break提前终止switch,当switch处在循环中,可通过break加标签的方式跳出外层循环。

5.3 类型选择

switch可用于判断接口变量的动态类型,如图5.3。

图5.3 动态类型判断

六 函数

6.1 可命名结果参数

Go返回值可命名,函数调用时,自动初始化为零值,直接用return不带变量,则结果形参的当前值会返回。

6.2 defer

defer会推迟执行函数,到调用defer的函数返回前立即执行,常用于资源释放。被推迟函数的实参在调用时确定,而不是执行时,defer函数的执行遵循LIFO。

七 数据

7.1 new分配

new(T)分配置零内存空间,并返回指针*T。

7.2 构造函数和复合字面

new(T)创建的对象,字段只有零值,没有初始化,可以new(T)后,给T的字段赋值,但更简洁的方法是使用复合字面来简化,例如:return &File{fd, name, nil, 0},复合字面的字段必须按顺序全部列出, 以字段:值对的形式明确地标出元素,初始化字段时就可以按任何顺序出现,未给出的字段值将赋予零值,例如:return &File{fd: fd, name: name}。

7.3 make分配

make只用于创建切片、map和通道,并返回类型为 T(而非 *T)的一个已初始化 (而非置零)的值。这三种类型本质上是引用类型,使用之前必须初始化,例如: 切片是一个具有三项内容的描述符,包含一个指向(数组内部)数据的指针、长度以及容量, 在这三项被初始化之前,该切片为 nil。因此创建slice的习惯用法为:v := make([]int, 100)

7.4 数组

与C不同:
1. 数组是值。将一个数组赋予另一个数组会复制其所有元素。若将某个数组传入某个函数,将接收到该数组的一份副本而非指针。
2. 数组的大小是其类型的一部分。类型 [10]int 和 [20]int 不同。
7.5 map
访问map中不存在的key时,返回value对应类型的零值,若要区分某项是零值还是真的不存在,可用seconds, ok = timeZone[tz]的形式。删除某项,可用delete(timeZone,tz),即使key不存在也不会报错。

7.6 变长参数

内置函数append的签名如下,因为不支持动态参数类型(范型),因此append函数需要编译器支持。
func append(slice []T, 元素 ...T) []T
要将一个切片的元素添加到另一切片中,用法如7.1:

图7.1 …用法

八 初始化

8.1 常量

枚举常量可用iota枚举器创建,如图8.1:

图8.1 iota枚举器

8.2 init函数

每个源文件都可以定义无参和返回值的init函数,用于设置初始化状态,或进行一些检查,init函数会被自动调用。初始化顺序为导入包初始化,本包变量初始化器初始化,调用init函数。

九 方法

9.1 指针和值

值方法可通过指针和值调用,而指针方法只能通过指针来调用;指针方法可以修改接收者,通过值调用它们会导致方法接收到该值的副本,任何修改都将被丢弃。
要修改接受者时用指针,如图9.1:

图9.1 指针方法

十 接口和其它类型

10.1 接口转换和类型判断

fmt.Printf类型选择简化版代码如图10.1:

图10.1 类型选择

单个类型判断如图10.2:

图10.2 类型判断

10.2 通用性(多态)

对于只实现了接口中的方法,无其它导出方法的类型,可通过方法返回接口实例,而无需关注实例的具体类型,类似面向对象中多态的思想。

十一 空白标识符

11.1 未使用的导入和变量

对于暂未使用的导入和变量,可用空白标志符防止编译报错,如图11.1:

图11.1 防止编译报错

11.2 副作用导入

例如需要导入包执行init初始化函数,但并不使用包。

图11.2 副作用导入

十二 嵌入

go没有子类的概念,但能通过内嵌的方式实现类似的功能(聚合转发的方式)。接口内嵌如下图12.1,ReadWriter接口会拥有Reader和Writer接口中的方法。

图12.1 接口内嵌

结构体内嵌如图12.2,Job会拥有Logger的所有方法。Job内实际上会拥有一个名称为Logger的变量,Logger类型的方法都会转发给Logger变量。

图12.2 结构体内嵌

可以自己初始化Logger字段,如图12.3,同时可以直接Job.Logger访问内嵌Logger字段。

图12.3 内嵌变量初始化

十三 错误

13.1 自定义错误类型

错误的接口内置类型为error,如图13.1:

图13.1 error接口

程序可以实现自己的错误类型,如图13.2,错误字符串应尽可能包含错误来源,比如包名前缀等。

图13.2 自定义错误类型

13.2 panic&recover

当程序产生不可恢复错误时,可使用panic,产生运行时错误,从而使协程退出。panic会终止函数继续运行,并回溯go协程栈,执行被defer的函数。
内建的 recover 函数可重新获取Go协程的控制权限并使其恢复正常执行,如图13.3:

图13.3 recover处理

参考文献

[1] 使用gofmt格式化代码.
[2] Mac下安装godoc
[3] Effective Go.
[4] Effective Go翻译版.

Effective Go笔记的更多相关文章

  1. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  2. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  3. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  4. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  5. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  6. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  7. java effective 读书笔记

    java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...

  8. Effective STL 笔记 -- Item 6 ~ 7: Container and Object Pointer

    Effective STL 笔记 – Item 6 ~ 7: Container and Object Pointer 中间两次笔记被删掉了,简单补一下: Item 3 中提到如果将对象直接放入容器中 ...

  9. Item 5:那些被C++默默地声明和调用的函数 Effective C++笔记

    Item 5: Know what functions C++ silently writes and calls 在C++中,编译器会自己主动生成一些你没有显式定义的函数,它们包含:构造函数.析构函 ...

  10. effective c++ 笔记 (1-3)

    // //  effective c++.cpp //  笔记 // //  Created by fam on 15/3/23. // // //-------------------------- ...

随机推荐

  1. spring:事务的5大隔离级别,7大传播行为

    一.五大隔离级别 ISOLATION_READ_UNCOMMITTED:读未提交 ISOLATION_READ_COMMITTED:读已提交 ISOLATION_REPEATABLE_READ:可重复 ...

  2. Redis Client 官方下载地址

    下载地址:https://github.com/caoxinyu/RedisClient 界面 归途(LM)

  3. JAVA异常处理原则和log4j输出详细异常分析

    1.多用try,catch;不要一个try,catch包含所有内容 好处:不同模块抓取不同异常,某一模块异常挂了,不影响其他模块的程序的进行 2.多写几个catche:尽量不要使用Exception这 ...

  4. 判断两个数组是否相似 (arraysSimilar)

    题目 解答 思路 具体实现代码 总结 题目 题目来自 慕课网 JavaScript 深入浅出 1-6 编程练习 请在 index.html 文件中,编写 arraysSimilar 函数,实现判断传入 ...

  5. montagy

    因为只是想分享ghcjs和webgl的使用经验,所以很多地方说的很粗,因为涉及的知识确实很多, 推荐两本书,一本haskell基础的 learn you a haskell for great goo ...

  6. 树的DFS

    Depth-first search (DFS) is an algorithm for traversing or searching tree or graph data structures. ...

  7. Ionic3学习笔记(十三)HttpClient 实现 HTTP 请求以及踩过的一些坑

    本文为原创文章,转载请标明出处 目录 猫眼API HttpClient 实现 HTTP 请求 安装 HttpClientModule 模块 创建 provider 创建 page 一些坑 坑1: 未在 ...

  8. yii2.0 集合七牛SDK 上传图片到第三方

    首先,请用composer下载七牛phpSDK (具体参考官方文档) composer require qiniu/php-sdk 注册七牛账号 获取 AK SK(密匙) ,创建资源对象 获取doma ...

  9. android 应用程序与服务端交互

    http://www.cnblogs.com/freeliver54/archive/2012/06/13/2547765.html 简述了Service的一些基础知识以及Service和Thread ...

  10. R语言入门级实例——用igragh包分析社群

    R语言入门级实例——用igragh包分析社群 引入—— 本文的主要目的是初步实现R的igraph包的基础功能,包括绘制关系网络图(social relationship).利用算法进行社群发现(com ...