设为首页收藏本站

LUPA开源社区

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

Go 语言 12 条最佳实践

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

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

越简洁越好

或者 长代码往往不是最好的.

试着使用能自解释的最短的变量名.

  • 用 MarshalIndent ,别用 MarshalWithIndentation.

别忘了包名会出现在你选择的标识符前面

  • In package encoding/json we find the type Encoder, not JSONEncoder.
  • It is referred as json.Encoder.

 

有多个文件的包

需要将一个包分散到多个文件中吗?

  • 避免行数非常多的文件

标准库中 net/http 包有47个文件,共计 15734 行.

  • 拆分代码并测试

net/http/cookie.go 和 net/http/cookie_test.go  都是 http 包的一部分.

测试代码 只有 在测试时才会编译.

  • 多文件包的文档编写

如果一个包中有多个文件, 可以很方便的创建一个 doc.go 文件,包含包文档信息.

让包可以”go get”到

一些包将来可能会被复用,另外一些不会.

定义了一些网络协议的包可能会在开发一个可执行命令时复用.

github.com/bradfitz/camlistore

 

接口

你需要什么

让我们以之前的Gopher类型为例

1
2
3
4
5
type Gopher struct {
    Name     string
    Age      int32
    FurColor color.Color
}

我们可以定义这个方法

1
func (g *Gopher) DumpToFile(f *os.File) error {

但是使用一个具体的类型会让代码难以测试,因此我们使用接口.

1
func (g *Gopher) DumpToReadWriter(rw io.ReadWriter) error {

进而,由于使用的是接口,我们可以只请求我们需要的.

1
func (g *Gopher) DumpToWriter(f io.Writer) error {

让独立的包彼此独立

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import (
    "code.google.com/p/go.talks/2013/bestpractices/funcdraw/drawer"
    "code.google.com/p/go.talks/2013/bestpractices/funcdraw/parser"
)
 
 // Parse the text into an executable function.
    f, err := parser.Parse(text)
    if err != nil {
        log.Fatalf("parse %q: %v", text, err)
    }
 
    // Create an image plotting the function.
    m := drawer.Draw(f, *width, *height, *xmin, *xmax)
 
    // Encode the image into the standard output.
    err = png.Encode(os.Stdout, m)
    if err != nil {
        log.Fatalf("encode image: %v", err)
    }

解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type ParsedFunc struct {
    text string
    eval func(float64) float64
}
 
func Parse(text string) (*ParsedFunc, error) {
    f, err := parse(text)
    if err != nil {
        return nil, err
    }
    return &ParsedFunc{text: text, eval: f}, nil
}
 
func (f *ParsedFunc) Eval(x float64) float64 { return f.eval(x) }
func (f *ParsedFunc) String() string         { return f.text }

描绘

1
2
3
4
5
6
7
8
import (
    "image"
 
    "code.google.com/p/go.talks/2013/bestpractices/funcdraw/parser"
)
 
// Draw draws an image showing a rendering of the passed ParsedFunc.
func DrawParsedFunc(f parser.ParsedFunc) image.Image {

使用接口来避免依赖.

import "image"

// Function represent a drawable mathematical function.
type Function interface {
    Eval(float64) float64
}

// Draw draws an image showing a rendering of the passed Function.
func Draw(f Function) image.Image {

测试

使用接口而不是具体类型让测试更简洁.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package drawer
 
import (
    "math"
    "testing"
)
 
type TestFunc func(float64) float64
 
func (f TestFunc) Eval(x float64) float64 { return f(x) }
 
var (
    ident = TestFunc(func(x float64) float64 { return x })
    sin   = TestFunc(math.Sin)
)
 
func TestDraw_Ident(t *testing.T) {
    m := Draw(ident)
    // Verify obtained image.

在接口中避免并发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func doConcurrently(job string, err chan error) {
    go func() {
        fmt.Println("doing job", job)
        time.Sleep(1 * time.Second)
        err <- errors.New("something went wrong!")
    }()
}
 
func main() {
    jobs := []string{"one", "two", "three"}
 
    errc := make(chan error)
    for _, job := range jobs {
        doConcurrently(job, errc)
    }
    for _ = range jobs {
        if err := <-errc; err != nil {
            fmt.Println(err)
        }
    }
}

如果我们想串行的使用它会怎样?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func do(job string) error {
    fmt.Println("doing job", job)
    time.Sleep(1 * time.Second)
    return errors.New("something went wrong!")
}
 
func main() {
    jobs := []string{"one", "two", "three"}
 
    errc := make(chan error)
    for _, job := range jobs {
        go func(job string) {
            errc <- do(job)
        }(job)
    }
    for _ = range jobs {
        if err := <-errc; err != nil {
            fmt.Println(err)
        }
    }
}

暴露同步的接口,这样异步调用这些接口会简单.

 


酷毙
1

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

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

最新评论

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

返回顶部