设为首页收藏本站

LUPA开源社区

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

Go 语言 12 条最佳实践

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

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

并发的最佳实践

 

使用goroutines管理状态

使用chan或者有chan的结构体和goroutine通信

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
type Server struct{ quit chan bool }
 
func NewServer() *Server {
    s := &Server{make(chan bool)}
    go s.run()
    return s
}
 
func (s *Server) run() {
    for {
        select {
        case <-s.quit:
            fmt.Println("finishing task")
            time.Sleep(time.Second)
            fmt.Println("task done")
            s.quit <- true
            return
        case <-time.After(time.Second):
            fmt.Println("running task")
        }
    }
}
 
func (s *Server) Stop() {
    fmt.Println("server stopping")
    s.quit <- true
    <-s.quit
    fmt.Println("server stopped")
}
 
func main() {
    s := NewServer()
    time.Sleep(2 * time.Second)
    s.Stop()
}

使用带缓存的chan,来避免goroutine内存泄漏

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
func sendMsg(msg, addr string) error {
    conn, err := net.Dial("tcp", addr)
    if err != nil {
        return err
    }
    defer conn.Close()
    _, err = fmt.Fprint(conn, msg)
    return err
}
 
func main() {
    addr := []string{"localhost:8080", "http://google.com"}
    err := broadcastMsg("hi", addr)
 
    time.Sleep(time.Second)
 
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println("everything went fine")
}
 
func broadcastMsg(msg string, addrs []string) error {
    errc := make(chan error)
    for _, addr := range addrs {
        go func(addr string) {
            errc <- sendMsg(msg, addr)
            fmt.Println("done")
        }(addr)
    }
 
    for _ = range addrs {
        if err := <-errc; err != nil {
            return err
        }
    }
    return nil
}
  • goroutine阻塞在chan写操作
  • goroutine保存了一个chan的引用
  • chan永远不会垃圾回收
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func broadcastMsg(msg string, addrs []string) error {
    errc := make(chan error, len(addrs))
    for _, addr := range addrs {
        go func(addr string) {
            errc <- sendMsg(msg, addr)
            fmt.Println("done")
        }(addr)
    }
 
    for _ = range addrs {
        if err := <-errc; err != nil {
            return err
        }
    }
    return nil
}

如果我们不能预测channel的容量呢?

使用quit chan避免goroutine内存泄漏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func broadcastMsg(msg string, addrs []string) error {
    errc := make(chan error)
    quit := make(chan struct{})
 
    defer close(quit)
 
    for _, addr := range addrs {
        go func(addr string) {
            select {
            case errc <- sendMsg(msg, addr):
                fmt.Println("done")
            case <-quit:
                fmt.Println("quit")
            }
        }(addr)
    }
 
    for _ = range addrs {
        if err := <-errc; err != nil {
            return err
        }
    }
    return nil
}

12条最佳实践

1. 避免嵌套的处理错误
2. 尽可能避免重复
3. 将重要的代码放前面
4. 为代码编写文档
5. 越简洁越好
6. 讲包拆分到多个文件中
7. 让包”go get”到
8. 按需请求
9. 让独立的包彼此独立
10. 在接口中避免并发
11. 使用goroutine管理状态
12. 避免goroutine内存泄漏

一些链接

资源

其他演讲

  • 用go做词法扫描 video
  • 并发不是并行 video
  • Go并发模式 video
  • Go高级并发模式 video

谢谢

Francesc Campoy Flores

Gopher at Google

@campoy83

http://campoy.cat/+


原文链接: Francesc Campoy Flores   翻译: 伯乐在线 Codefor
译文链接: http://blog.jobbole.com/44608/

酷毙
1

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

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

最新评论

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

返回顶部