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
- Goroutine is cheap,not free(每个goroutine约占用6k的内存,实际代码很容易达到15-30K)
- 设计系统时要能预见并控制goroutine的总数,必要时可以发放ticket来控制资源
- 避免滥用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
}
避免大对象的拷贝
- 如果map的value较大,通常应该使用指针来存储,以避免性能问题,类似的还有channel,slice等
- 避免[]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)
}