Golang 的个人建议

RPC 监控

用浏览器打开网址 http://ip:port/debug/rpc 可以看到rpc各个函数的调用次数

导出关键变量

import _ "expvar"
导出变量为json格式,便于分析和绘图,有利于编写自动化监控程序

HTTP接口监控程序

import _ "net/http/pprof“
go func() {      
    http.ListenAndServe("localhost:   6060", nil) 
}()
随时观察程序状态(goroutine, heap, thread)
随时可以profile程序(go tool pprof http://localhost:6060/debug/pprof)

Go - Format 格式化代码

Goroutine

  1. Goroutine is cheap,not free(每个goroutine约占用6k的内存,实际代码很容易达到15-30K)
  2. 设计系统时要能预见并控制goroutine的总数,必要时可以发放ticket来控制资源
  3. 避免滥用goroutine,不合理的并行会带来更多的bug,也让问题难以复现和调试

链接池

func (p *ConnectionPool) InitPool(size int, f FactoryMethod) {
      p.conn = make(chan interface{}, size)
      for i := 0; i < size; i++ {
          p.conn <-  f()
  }
  p.size = size
}
	
func (p *ConnectionPool) Get() interface{} {	
  return <-p.conn	
}
	
func (p *ConnectionPool) Put(conn interface{}) {
  p.conn <- conn
}

避免大对象的拷贝

  1. 如果map的value较大,通常应该使用指针来存储,以避免性能问题,类似的还有channel,slice等
  2. 避免[]byte和string的反复来回转换

写Func时,最好可以返回一个 error

func (ns NullString) Value() (driver.Value, error) {
	if !ns.Valid {
		return nil, nil
	}
	return ns.String, nil
}

Go的共享哲学

Don't communicate by shared memory.

Instead, share memory by communicating.

---- Rob Pike

组合来实现继承

sturct 通过组合匿名成员来达到继承的形式时,当此 struct 调用一个方法,如果其本身没有实现此方法,编译器会自动的搜索其匿名成员下是否有实现了此方法,如果实现了,则调用成功,否则就失败

Tips: 如果此 struct 有多个匿名成员都实现了一个同名方法,则在编写时,调用此方法,才会报错!组合时并不会

注意如下的代码,输出的结果,会与预期的结果有出入:

匿名组合之后,期望的输出与实际输出的差异

Map

使用make函数一个合理元素数量参数,有助于提升性能。避免后续操作时频繁扩张。

Map中取也的Value其实是临时复制品,对其成员的修改并没有任何意义

如果要修改其中的值,需要转换成指针

在迭代时可以安全删除键值。但如果期间有新增操作,可能会有意外的结果

for i := 0; i < 5; i++ {
    m := map[int]string{
      0: "a", 1: "a", 2: "a", 3: "a", 4: "a",
      5: "a", 6: "a", 7: "a", 8: "a", 9: "a",
    }
   for k := range m {
      m[k+k] = "x"
      delete(m, k)
   }
   fmt.Println(m)
}