推荐:Golang工具大全,提升你的编程效率

发表时间: 2024-03-12 10:57

go-callvis-代码调用关系的可视化工具

go-callvis是一个代码调用关系的可视化工具,它可以帮助我们了解指定项目代码的结构,以达到更快的理解代码意图的目的。

工具使用简单,步骤如下:

// 1. 安装git clone https://github.com/ofabry/go-callvis.gitcd go-callvis && make install// 2. 以著名golang开源项目bigcache 的main函数为入口,分析代码调用关系(不打开浏览器 | 忽略标准库的方法)go-callvis -skipbrowser -nostd ./server/// 3. 访问http://localhost:7878查看调用关系矢量图

调用关系矢量图怎么看,一共分为三个部分:

Packages / Types(包)

Represents

Style

focused(需要关注的)

blue color(蓝色)

stdlib(标准库)

green color(绿色)

other(其他包)

yellow color(黄色)

Functions / Methods(函数方法)

Represents

Style

exported(导出的包)

bold border(粗边框)

unexported(未导出包)

normal border(正常边框)

anonymous(匿名包)

dotted border(虚线边框)

Calls(调用)

Represents

Style

internal(内部)

black color(黑色)

external(外部)

brown color(棕色)

static(静态函数)

solid line(实线)

dynamic(动态函数)

dashed line(虚线)

regular(常规函数)

simple arrow(简单箭头)

concurrent(协程)

arrow with circle(箭头带圆圈)

deferred(defer)

arrow with diamond(箭头带菱形)

gotests-自动生成单测用例框架

gotests工具可以帮我们自动生成单测用例框架,这样以来,我们只需要关注需要测试的业务代码逻辑即可,省去了大量的拷贝复制的重复劳动。

gotest工具使用也是十分方便,可以直接安装(go get -u
github.com/cweill/gotests/...)后用命令行($ gotests [options] PATH ...)的方式,或者也可以作为IDE的插件直接使用,如Emacs,Vim,Atom Editor,Visual Studio Code, andIntelliJ Goland. 这里以VS Code为例:

// 一个简单工厂模式代码实现package simplefactoryimport "fmt"//API is interfacetype API interface {	Say(name string) string}//NewAPI return Api instance by typefunc NewAPI(t int) API {	if t == 1 {		return &hiAPI{}	} else if t == 2 {		return &helloAPI{}	}	return nil}//hiAPI is one of API implementtype hiAPI struct{}//Say hi to namefunc (*hiAPI) Say(name string) string {	return fmt.Sprintf("Hi, %s", name)}//HelloAPI is another API implementtype helloAPI struct{}//Say hello to namefunc (*helloAPI) Say(name string) string {	return fmt.Sprintf("Hello, %s", name)}

自动生成的测试用例框架,如下:

PS D:\code\golang-design-pattern\00_simple_factory> gotests.exe  -all .\simple.goGenerated TestNewAPIGenerated Test_hiAPI_SayGenerated Test_helloAPI_Saypackage simplefactoryimport (        "reflect"        "testing")func TestNewAPI(t *testing.T) {        type args struct {                t int        }        tests := []struct {                name string                args args                want API        }{                // TODO: Add test cases.        }        for _, tt := range tests {                t.Run(tt.name, func(t *testing.T) {                        if got := NewAPI(tt.args.t); !reflect.DeepEqual(got, tt.want) {                                t.Errorf("NewAPI() = %v, want %v", got, tt.want)                        }                })        }}func Test_hiAPI_Say(t *testing.T) {                })        }}func Test_helloAPI_Say(t *testing.T) {        type args struct {                name string        }        tests := []struct {                name string                h    *helloAPI                args args                want string        }{                // TODO: Add test cases.        }        for _, tt := range tests {                t.Run(tt.name, func(t *testing.T) {                        h := &helloAPI{}                        if got := h.Say(tt.args.name); got != tt.want {                                t.Errorf("helloAPI.Say() = %v, want %v", got, tt.want)                        }                })        }}PS D:\code\golang-design-pattern\00_simple_factory>

go-multierror-多错误管理

在关于使用 Go 语言的时候,开发者面对最大的挑战的年度调查中,错误(error)管理总是能引起很多争论。在并发环境处理 error 的场景下,或者在同一个 goroutine 中合并多个错误的场景下,Go 提供了很不错的包可以让多个错误的处理变得简单:来看看如何合并由单个 goroutine 生成的多个 error。

go-multierror提供了常用的多错误管理四种方式:

Building a list of errors / Accessing the list of errors / Checking for an exact error value

构建错误返回列表 / 访问误返回列表 / 检查错误列表中是否包含某个错误

package mainimport (    "fmt"    "errors"    multierror"github.com/hashicorp/go-multierror")func step1() error {    return errors.New("xhihu")}func step2() error {    return errors.New("yhihu")}func main() {    var result error    if err := step1(); err != nil {        result = multierror.Append(result, err)    }    if err := step2(); err != nil {        result = multierror.Append(result, err)    }    fmt.Printf(result.Error())    if merr, ok := result.(*multierror.Error); ok {        // Use merr.Errors        // merr.Errors -> []error        }    if errors.Is(result, os.ErrNotExist) {	// err contains os.ErrNotExist    }    return}

Customizing the formatting of the errors / 自定义多错误时显示的整体的打印信息

var result *multierror.Error// ... accumulate errors here, maybe using Appendif result != nil {	result.ErrorFormat = func([]error) string {		return "errors!"	}}

goleak-内存泄漏检查

goroutine 泄漏会导致内存中存活的 goroutine 数量不断上升,直到把主机的CPU和内存全部吃爆,最终以服务宕机为止。所以,我们会想到有没有一种方法,可以在代码部署之前,来检查程序中是否存在goroutine 泄漏。

Uber 公司的 Go 团队在 GitHub 开源了他们的goroutine 泄漏检测器出来,一个与单元测试结合使用的工具。 goleak 可以监控当前测试代码中泄漏的 goroutine。下面有一个 goroutine 泄漏的例子:

//demo.gofunc leak() error {    go func() {        time.Sleep(time.Minute)    }()    return nil}//demo_test.gofunc TestLeakFunction(t *testing.T) {    defer goleak.VerifyNone(t)    if err := leak(); err != nil {        t.Fatal("error not expected")    }}

用例直接报错了,从报错信息中我们可以看到泄露的goroutine 的堆栈信息,以及 goroutine 的状态。

pprof性能分析+火焰图

Pprof是一个用于采样数据可视化和分析的工具。主要分析服务运行过程产生的:阻塞同步的堆栈信息,所有的goroutine堆栈信息,活动对象的内存分配信息,互斥锁的竞争持有者的堆栈,默认进行30s的CPU采样信息,查看创建新OS线程的堆栈信息等等。

我们可以利用prof进行性能监控,且可以生成监控信息文件,方便后续分析性能瓶颈或者是内存泄漏情况。

package mainimport (    "fmt"    "time"    "log"    "net/http"    _ "net/http/pprof"    "os"    "runtime")func alloc(outCh chan<- int) {        buf := make([]byte, 1024)        outCh <- 0}func Leak() {        outCh := make(chan int)        go func() {                if false {                        <-outCh                }                select {}        }()        tick := time.Tick(time.Second / 100)        i := 0        for range tick {                i++                fmt.Println(i)                //一直分配内存,不释放放                go alloc(outCh)}func main() {    log.SetFlags(log.Lshortfile | log.LstdFlags)    log.SetOutput(os.Stdout)    runtime.GOMAXPROCS(1)    runtime.SetMutexProfileFraction(1)    runtime.SetBlockProfileRate(1)    // 需要性能分析的业务逻辑    go Leak()    go func() {        // 通过http://locahost:6060/debug/pprof进行查看相关的监控信息文件        if err := http.ListenAndServe(":6060", nil); err != nil {            log.Fatal(err)        }        os.Exit(0)    }()    select{}}1. go build  prof_demo.go2. ./prof_demo3. 手动登陆浏览器,通过http://locahost:6060/debug/pprof进行查看相关的监控信息文件4. go install github.com/google/pprof@latest5. yum install graphviz// 查看火焰图6. pprof -http=:6061  http://192.168.159.140:6060/debug/pprof/profile

jsoniter-高性能json序列化工具

go语言多数用于云原生中的网咯服务,因此一个常见的场景就是数据的序列化和反序列化,一般都是利用json进行。这里推荐采用jsoniter替换掉go原生encoding/json,两者接口一致,但jsoniter的性能远远超过encoding/json,Benchmark详见如下:


ns/op

allocation bytes

allocation times

std decode

35510 ns/op

1960 B/op

99 allocs/op

easyjson decode

8499 ns/op

160 B/op

4 allocs/op

jsoniter decode

5623 ns/op

160 B/op

3 allocs/op

import jsoniter "github.com/json-iterator/go"var json = jsoniter.ConfigCompatibleWithStandardLibraryjson.Marshal(&data)json.Unmarshal(input, &data)

Reference

Go代码调用链路可视化工具—go-callvis - 知乎 (zhihu.com)

GoTests工具自动化test使用 - 掘金 (juejin.cn)

Go: Multiple Errors Management. Error management in Go is always prone… | by Vincent Blanchon | A Journey With Go | Medium

Fastest JSON parser ever (jsoniter.com)

Go:多错误管理 - Go语言中文网 - Golang中文社区 (studygolang.com)

GitHub - hashicorp/go-multierror: A Go (golang) package for representing a list of errors as a single error

Go: Goroutine 泄漏检查器 - Go语言中文网 - Golang中文社区 (studygolang.com)

golang性能优化之pprof及其火焰图 - 简书 (jianshu.com)

Golang-PProf之性能剖析_-Xx.。的博客-CSDN博客_golang pprof allocs 解释