一 格式化

使用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. Mr.Yu

    在linux下搭建Git服务器 git服务器环境 服务器 CentOS7 + git(version 1.8.3.1)客户端 Windows10 + git(version 2.16.0.window ...

  2. 从NIPS2014大会看机器学习新趋势

    微软杰出科学家 John Platt 本文译自:Machine Learning Trends fromNIPS 2014 编者按:John Platt是微软的杰出科学家,也是微软在机器学习领域的领军 ...

  3. 【转】蛋糕尺寸(寸)、尺寸(CM)、重量(磅)、食用人数对照换算参考表

    转自:https://www.douban.com/note/324832054/ 蛋糕尺寸(寸).尺寸(CM).重量(磅).食用人数对照换算参考表 馋嘴猫DIY烘焙 2014-01-04 12:15 ...

  4. vue基础指令了解

    Vue了解 """ vue框架 vue是前台框架:Angular.React.Vue vue:结合其他框架优点.轻量级.中文API.数据驱动.双向绑定.MVVM设计模式. ...

  5. springboot ——oracle.jdbc.driver.OracleDriver

    网上很多案例讲是oracle的驱动包没有导入进去,我之前尝试下图示方式导入解决该问题: 但是在后期调试的时候,发现会影响后续oracle数据源连接驱动的问题,导致不能查询,因此想,另辟途径,解决这个问 ...

  6. 记 MySQL优化 20条

    1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的.当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一 ...

  7. CSS的五种定位方式

    CSS中一共有五种定位: position:static:默认值 position:absolute:绝对定位 position:relative:相对对定位 position:fixed:固定定位 ...

  8. Python学习笔记--gevent嵌套使用

    这篇主要是接着上篇的,实验gevent嵌套使用,看情况如何.还是先上代码. #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2020-0 ...

  9. 手把手教你如何用MSF进行后渗透测试!

    在对目标进行渗透测试的时候,通常情况下,我们首先获得的是一台web服务器的webshell或者反弹shell,如果权限比较低,则需要进行权限提升:后续需要对系统进行全面的分析,搞清楚系统的用途:如果目 ...

  10. beego的安装以及bee的安装和使用

    beego的安装以及bee的安装和使用 一.beego的安装 1.beego是什么 beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API.Web 及后端服务等各种应用, ...