当前位置:首页 > 技术分析 > 正文内容

超好用的golang工具分享_golang开发工具 推荐

ruisui883个月前 (02-07)技术分析12

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

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

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

// 1. 安装
git clone https://github.com/ofabry/go-callvis.git
cd 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 simplefactory

import "fmt"

//API is interface
type API interface {
	Say(name string) string
}

//NewAPI return Api instance by type
func NewAPI(t int) API {
	if t == 1 {
		return &hiAPI{}
	} else if t == 2 {
		return &helloAPI{}
	}
	return nil
}

//hiAPI is one of API implement
type hiAPI struct{}

//Say hi to name
func (*hiAPI) Say(name string) string {
	return fmt.Sprintf("Hi, %s", name)
}

//HelloAPI is another API implement
type helloAPI struct{}

//Say hello to name
func (*helloAPI) Say(name string) string {
	return fmt.Sprintf("Hello, %s", name)
}

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

PS D:\code\golang-design-pattern\00_simple_factory> gotests.exe  -all .\simple.go
Generated TestNewAPI
Generated Test_hiAPI_Say
Generated Test_helloAPI_Say
package simplefactory

import (
        "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 main

import (
    "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 Append

if result != nil {
	result.ErrorFormat = func([]error) string {
		return "errors!"
	}
}

goleak-内存泄漏检查

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

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

//demo.go
func leak() error {
    go func() {
        time.Sleep(time.Minute)
    }()

    return nil
}

//demo_test.go
func 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 main

import (
    "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.go

2. ./prof_demo

3. 手动登陆浏览器,通过http://locahost:6060/debug/pprof进行查看相关的监控信息文件

4. go install github.com/google/pprof@latest

5. 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.ConfigCompatibleWithStandardLibrary
json.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 解释

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/1759.html

标签: pprof
分享给朋友:

“超好用的golang工具分享_golang开发工具 推荐” 的相关文章

体检刷卡收费管理系统

体检刷卡收费管理系统headerfooter《体检刷卡收费管理系统》是针对各医院进行体检刷卡收费管理的一套系统。软件集办卡、充值、刷卡消费、体检登记与一体。主要功能:1.基本信息:科室设置、套餐设置、单项设置、本院信息;2.体检卡管理:单位人员办卡、个人办卡、体检卡充值、体检卡禁用、体检卡开通、体检...

【Vue3 基础】05.组件化

这是 Vue3 + Vite + Pinia +TS + Element-Plus 实战系列文档。最近比较忙没什么时间写文章,争取早日把这个系列完结吧~生命周期和模板引用在本章之前,我们通过响应式 api 和声明式渲染,处理了 DOM 的更新,但光是这些,对于一些复杂的需要手动操作 DOM 的情况,...

vue中如何在自定义组件上使用v-model和.sync

自定义事件tips推荐始终使用 kebab-case 的事件名。(v-on会将事件名自动转换为小写,避免匹配不到)changeData ×change-data √自定义组件的v-model用法:父组件定义数据源(不需要定义修改数据的方法),在子组件标签上通过v-model="data...

Python 幕后:Python导入import的工作原理

更多互联网精彩资讯、工作效率提升关注【飞鱼在浪屿】(日更新)Python 最容易被误解的方面其中之一是import。Python 导入系统不仅看起来很复杂。因此,即使文档非常好,它也不能让您全面了解正在发生的事情。唯一方法是研究 Python 执行 import 语句时幕后发生的事情。注意:在这篇文...

一次Java内存占用高的排查案例,解释了我对内存问题的所有疑问

问题现象7月25号,我们一服务的内存占用较高,约13G,容器总内存16G,占用约85%,触发了内存报警(阈值85%),而我们是按容器内存60%(9.6G)的比例配置的JVM堆内存。看了下其它服务,同样的堆内存配置,它们内存占用约70%~79%,此服务比其它服务内存占用稍大。那为什么此服务内存占用稍大...

Python中的11 种数组算法

1. 创建数组 创建数组意味着留出一个连续的内存块来存储相同类型的元素。在大多数语言中,您可以在创建数组时指定数组的大小。假设您正在书架上整理一组书籍,并且您需要为正好 10 本书预留空间。功能架上的每个空间都对应于数组中的一个索引。# Example in Python arr = [1, 2,...