设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

Go 语言 12 条最佳实践

2013-8-2 09:56| 发布者: 红黑魂| 查看: 3355| 评论: 0|来自: 伯乐在线

摘要: 本文来自 Google 工程师 Francesc Campoy Flores 分享的幻灯片。内容包括:代码组织、API、并发最佳实践和一些推荐的相关资源。最佳实践维基百科的定义是:“最佳实践是一种方法或技术,其结果始终优于其他方式。” ...

本文来自 Google 工程师 Francesc Campoy Flores 分享的幻灯片。内容包括:代码组织、API、并发最佳实践和一些推荐的相关资源。

 

最佳实践

维基百科的定义是:

“最佳实践是一种方法或技术,其结果始终优于其他方式。”

写Go代码的目标就是:

  • 简洁
  • 可读性强
  • 可维护性好

样例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type Gopher struct {
    Name     string
    Age      int32
    FurColor color.Color
}
 
func (g *Gopher) DumpBinary(w io.Writer) error {
    err := binary.Write(w, binary.LittleEndian, int32(len(g.Name)))
    if err == nil {
        _, err := w.Write([]byte(g.Name))
        if err == nil {
            err := binary.Write(w, binary.LittleEndian, g.Age)
            if err == nil {
                return binary.Write(w, binary.LittleEndian, g.FurColor)
            }
            return err
        }
        return err
    }
    return err
}

避免嵌套的处理错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func (g *Gopher) DumpBinary(w io.Writer) error {
    err := binary.Write(w, binary.LittleEndian, int32(len(g.Name)))
    if err != nil {
        return err
    }
    _, err = w.Write([]byte(g.Name))
    if err != nil {
        return err
    }
    err = binary.Write(w, binary.LittleEndian, g.Age)
    if err != nil {
        return err
    }
    return binary.Write(w, binary.LittleEndian, g.FurColor)
}

减少嵌套意味着提高代码的可读性

尽可能避免重复

功能单一,代码更简洁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type binWriter struct {
    w   io.Writer
    err error
}
 
// Write writes a value into its writer using little endian.
func (w *binWriter) Write(v interface{}) {
    if w.err != nil {
        return
    }
    w.err = binary.Write(w.w, binary.LittleEndian, v)
}
 
func (g *Gopher) DumpBinary(w io.Writer) error {
    bw := &binWriter{w: w}
    bw.Write(int32(len(g.Name)))
    bw.Write([]byte(g.Name))
    bw.Write(g.Age)
    bw.Write(g.FurColor)
    return bw.err
}

使用类型推断来处理特殊情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Write writes a value into its writer using little endian.
func (w *binWriter) Write(v interface{}) {
    if w.err != nil {
        return
    }
    switch v.(type) {
    case string:
        s := v.(string)
        w.Write(int32(len(s)))
        w.Write([]byte(s))
    default:
        w.err = binary.Write(w.w, binary.LittleEndian, v)
    }
}
 
func (g *Gopher) DumpBinary(w io.Writer) error {
    bw := &binWriter{w: w}
    bw.Write(g.Name)
    bw.Write(g.Age)
    bw.Write(g.FurColor)
    return bw.err
}

类型推断的变量声明要短

1
2
3
4
5
6
7
8
9
10
11
12
13
// Write write the given value into the writer using little endian.
func (w *binWriter) Write(v interface{}) {
    if w.err != nil {
        return
    }
    switch v := v.(type) {
    case string:
        w.Write(int32(len(v)))
        w.Write([]byte(v))
    default:
        w.err = binary.Write(w.w, binary.LittleEndian, v)
    }
}

函数适配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
func init() {
    http.HandleFunc("/", handler)
}
 
func handler(w http.ResponseWriter, r *http.Request) {
    err := doThis()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        log.Printf("handling %q: %v", r.RequestURI, err)
        return
    }
 
    err = doThat()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        log.Printf("handling %q: %v", r.RequestURI, err)
        return
    }
}
 
func init() {
    http.HandleFunc("/", errorHandler(betterHandler))
}
 
func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        err := f(w, r)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            log.Printf("handling %q: %v", r.RequestURI, err)
        }
    }
}
 
func betterHandler(w http.ResponseWriter, r *http.Request) error {
    if err := doThis(); err != nil {
        return fmt.Errorf("doing this: %v", err)
    }
 
    if err := doThat(); err != nil {
        return fmt.Errorf("doing that: %v", err)
    }
    return nil
}

如何组织代码

 

将重要的代码放前面

版权信息,构建信息,包说明文档

Import 声明,相关的包连起来构成组,组与组之间用空行隔开.。

1
2
3
4
5
6
7
import (
    "fmt"
    "io"
    "log"
 
    "code.google.com/p/go.net/websocket"
)

接下来代码以最重要的类型开始,以工具函数和类型结束。

 

如何编写文档

包名之前要写相关文档

1
2
3
// Package playground registers an HTTP handler at "/compile" that
// proxies requests to the golang.org playground service.
package playground

导出的标识符(译者按:大写的标识符为导出标识符)会出现在 godoc中,所以要正确的编写文档。

1
2
3
4
5
6
7
8
9
// Author represents the person who wrote and/or is presenting the document.
type Author struct {
    Elem []Elem
}
 
// TextElem returns the first text elements of the author details.
// This is used to display the author' name, job title, and company
// without the contact details.
func (p *Author) TextElem() (elems []Elem) {

生成的文档示例

Gocode: 文档化Go代码

 


酷毙
1

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部