这是我参与[第五届青训营]伴学笔记创作活动的第3天。
错误判定
- 判定一个错误是否为特定错误,使用
errors.Is - 不同于使用==, 使用该方法可以判定错误链上的所有错误是否含有特定的错误。
data, err := lockedfile.Read(targ)
if errors.Is(err, fs.ErrNotExist) {
// Treat non-existent as empty, to bootstrap the "latest" file
// the first time we connect to a given database.
return []byte{}, nil
}
return data, err
}
- 在错误链上获取特定种类的错误,使用errors.As
if _, err := os.Open("non-existing"); err != nil {
var pathError *fs.PathError
if errors.As(err, &pathError) {
fmt.Println("Failed at path:", pathError.Path)
} else {
fmt.Println(err)
}
}
- defer语句会在函数返回前调用
- 多个defer语句时后进先出
// 最终输出 31
func main() {
if true {
defer fmt.Println("1")
} else {
defer fmt.Printf("2")
}
defer fmt.Printf("3")
}
pprof
package main
import (
"fmt"
"net/http"
"sync"
"time"
_ "net/http/pprof"
)
// Some function that does work
func hardWork(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Start: %v\n", time.Now())
// Memory
a := []string{}
for i := 0; i < 500000; i++ {
a = append(a, "aaaa")
}
// Blocking
time.Sleep(2 * time.Second)
fmt.Printf("End: %v\n", time.Now())
}
func main() {
var wg sync.WaitGroup
// Server for pprof
go func() {
fmt.Println(http.ListenAndServe("localhost:6060", nil))
}()
wg.Add(1) // pprof - so we won't exit prematurely
wg.Add(1) // for the hardWork
go hardWork(&wg)
wg.Wait()
}
使用pprof进行可视化和分析剖面数据。 Go pprof 提供了以下五个不同的维度来观察它的程序。
- CPU Profiling : CPU性能分析,根据指定的时间集合监听其围棋程序的CPU使用情况,可以判断围棋程序在哪个程序段长时间消耗CPU。
- Memory Profiling:内存性能分析,用于分析程序的内存栈区使用情况,检测是否存在内存泄漏。
- Block Profiling : Goroutine 等待共享资源阻塞分析。
- Mutex Profiling:互斥锁分析,用于报告使用互斥锁的共享资源争用情况。
- Goroutine Profiling:并发性能分析,用于报告当前运行时的 Goroutine 操作及其数量。
go pprof工具也比较简单快速,可以使用runtime/pprofpackage生成profile文件,网上教程很多,这里就不过多介绍了,具体可以看功能提供的package ,其中describes 用法如上所述。
目前主要是使用net/http/pprofpackage启动一个单独的端口号http程序进行Go程序分析,配合graphviz组件可视化程序分析数据,也比较好用。