Uber 是一家美国硅谷的科技公司,也是 Go 语言的早期 adopter。其开源了很多 golang 项目,诸如被 Gopher 圈熟知的 zap、jaeger 等。2018 年年末 Uber 将内部的 Go 风格规范 开源到 GitHub,经过一年的积累和更新,该规范已经初具规模,并受到广大 Gopher 的关注,本文是对规范的整理
来源:https://github.com/xxjwxc/uber_go_guide_cn
1. 参数和返回(slice & map) slice
和 map
包含了指向底层数据的指针,因此当在函数中使用他们作为参数和返回值时,需要特别注意。
1.1 作为参数 a. 反面示例 type User struct { Likes []string }func (u *User) SetLikes(likes []string ) { u.Likes = likes }func TestRun (t *testing.T) { like := []string {"篮球" , "旅游" , "听歌" } user := new (User) user.SetLikes(like) fmt.Println("user Like1: " , user.Likes) like[1 ] = "学习" fmt.Println("user Like2 : " , user.Likes) }
b. 推荐写法 func (u *User) SetLikes(likes []string ) { u.Likes = make ([]string , len (likes)) copy (u.Likes, likes) }
1. 2 作为返回值 a. 反面示例 type Stats struct { mu sync.Mutex counters map [string ]int }func (s *Stats) Snapshot() map [string ]int { s.mu.Lock() defer s.mu.Unlock() return s.counters } snapshot := stats.Snapshot()
b. 推荐写法 type Stats struct { mu sync.Mutex counters map [string ]int }func (s *Stats) Snapshot() map [string ]int { s.mu.Lock() defer s.mu.Unlock() result := make (map [string ]int , len (s.counters)) for k, v := range s.counters { result[k] = v } return result } snapshot := stats.Snapshot()
2.结构体嵌入
嵌入的类型,应放在结构体内字段列表的顶部,并且必须有一个空行将嵌入式字段与常规字段分隔开。
2.1 反面示例 type Client struct { version int http.Client }
2.2 推荐写法 type Client struct { http.Client version int }
3. 初始化结构体 3.1 使用字段名初始化 k := User{"John" , "Doe" , true } k := User{ FirstName: "John" , LastName: "Doe" , Admin: true , }
3.2 对零值结构使用 var
如果在声明中省略了结构的所有字段,请使用 var
声明结构。
user := User{}var user User
3.3 初始化Struct
引用 在初始化结构引用时,请使用&T{}
代替new(T)
,以使其与结构体初始化一致。
sval := T{Name: "foo" } sptr := new (T) sptr.Name = "bar" sval := T{Name: "foo" } sptr := &T{Name: "bar" }
4. nil 是一个有效的slice 4.1 当返回长度为零的切片时 if x == "" { return []int {} }if x == "" { return nil }
4.2 检查切片是否为空
要检查切片是否为空,请始终使用len(s) == 0
。而非 nil
。
func isEmpty (s []string ) bool { return s == nil }func isEmpty (s []string ) bool { return len (s) == 0 }
4.3 零值切片 零值切片(用var
声明的切片)可立即使用,无需调用make()
创建。
a. 反面示例 nums := []int {}if add1 { nums = append (nums, 1 ) }if add2 { nums = append (nums, 2 ) }
b. 推荐写法 var nums []int if add1 { nums = append (nums, 1 ) }if add2 { nums = append (nums, 2 ) }