尝试golang的CI Golang基于Gitlab CI/CD部署方案 环境 gitlab: docker,gitlab docker,gitlab-runner 用于集成部署的镜像制作,golang版本,和一些必须的工具(golint等) runner 注册和配置 定义规则,.gitlab-ci.yml 获取列表,go list ./... | grep -v /vendor/ 单元测试, go test -short 数据竞争, go test -race -short 代码覆盖率 构建 linter github + travis-ci: 先整理一个本地的测试方案 按照travis的golang指导写.travis-ci.yml 参考: language: go go: - 1.9 - 1.8 - 1.7 branches: only: - master cache: directories: - $GOPATH/pkg/dep env: - DEP_VERSION="0.3.2" before_install: # Setup some env variables - GO_FILES=$(find . -iname '*.go' | grep -v /vendor/) # All the .go files, excluding vendor/ - PKGS=$(go list ./... | grep -v /vendor/) # All the import paths, excluding vendor/ # Setup dependency management tool - curl -L -s https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 -o $GOPATH/bin/dep - chmod +x $GOPATH/bin/dep # To install latest version, use `go get -u github.com/golang/dep/cmd/dep` # Install linters - go get -u github.com/golang/lint/golint # Linter - go get -u honnef.co/go/tools/cmd/megacheck # Badass static analyzer/linter - go get -u github.com/kisielk/errcheck # errcheck checks that you checked errors. # Install goveralls, Go integration for Coveralls.io. - go get -u github.com/mattn/goveralls install: - dep ensure script: - test -z $(gofmt -s -l $GO_FILES) # Fail if a .go file hasn't been formatted with gofmt - go vet $PKGS # go vet is the official Go static analyzer - megacheck $PKGS # "go vet on steroids" + linter - errcheck $PKGS # Check for unchecked errors - golint -set_exit_status $PKGS # One last linter # Run all the tests, track coverage in coveralls.io - go test -v -covermode=count -coverprofile=profile.cov $PKGS - goveralls -coverprofile=profile.cov -service=travis-ci
Posts
go doc godoc 命令godoc是一个很强大的工具,同样用于展示指定代码包的文档。并且提供网页选择。 开启godoc -http=localhost:6060。 可以在官方包之后的third-party部分找到对应的GOPATH里面自己的或下载的其他包。 go_doc go doc命令可以打印附于Go语言程序实体上的文档。我们可以通过把程序实体的标识符作为该命令的参数来达到查看其文档的目的。 下面是一个包的go doc输出: package suite // import "learning/cobra_demo/download_suite/suite" Package suite to download one suite images. Now support meituri. func DonwloadSuite(iSuite ISuiteOperator, countFanOut int, folderPath string, title string) func IsDir(path string) bool func IsFile(path string) bool func IsFileOrFolderExists(path string) bool type ISuiteOperator interface{ ... } type MeituriSuite struct{ ... } func NewMeituriSuite(firstPage string) *MeituriSuite 还支持其他参数,-all可以一并显示文档等。
goroutine channel的坑 channel的关闭 for-range 知道channel的关闭,代码继续执行 for-select 不知道,用case v, ok:=<-c:中的ok来判断 那么问题来了,如果是一个buffer channel,ok在关闭的时候可不是true,而是满足channel数据去完&channel close,ok才会返回true,如果不这样设计的话,会导致数据丢失。 channel for-select 中break和return的问题 核心是,break在select中是只能跳出select,return是返回当前的函数。 package meituri import "fmt" type ISuiteOperator interface { GetPageURLs(chan string) GetImgURLs(chPage <-chan string, chFailedImg <-chan string) <-chan string Download(chImg <-chan string, chFailedImg chan string, folderPath string) <-chan string } // DonwloadSuite to download one suite func DonwloadSuite(iSuite ISuiteOperator, countFanOut int, folderPath string) { chPage := make(chan string) chFailedImg := make(chan string) // 下载失败img放回 go iSuite.GetPageURLs(chPage) var chImgs []<-chan string for i := 0; i < countFanOut; i++ { ch := iSuite.GetImgURLs(chPage, chFailedImg) chImgs = append(chImgs, ch) } // 回收多个channel的结果 chImg := merge(chImgs...) // for debug // for { // select { // case v, ok := <-chImg: // if !ok { // return // } // fmt.Println(v, ok) // } // } var chDownloads []<-chan string for i := 0; i < countFanOut; i++ { ch := iSuite.Download(chImg, chFailedImg, folderPath) chDownloads = append(chDownloads, ch) } finish := merge(chDownloads...) for ret := range finish { fmt.Println("finish: ", ret) } } 在上面的代码中,chImg在merge结果的时候,注释代码是去测试结果的。 ...
Profiling 在计算机性能调试领域里,profiling 就是对应用的画像,这里画像就是应用使用 CPU 和内存的情况。也就是说应用使用了多少 CPU 资源?都是哪些部分在使用?每个函数使用的比例是多少?有哪些函数在等待 CPU 资源?知道了这些,我们就能对应用进行规划,也能快速定位性能瓶颈。 在 go 语言中,主要关注的应用运行情况主要包括以下几种: CPU profile:报告程序的 CPU 使用情况,按照一定频率去采集应用程序在 CPU 和寄存器上面的数据 Memory Profile(Heap Profile):报告程序的内存使用情况 Block Profiling:报告 goroutines 不在运行状态的情况,可以用来分析和查找死锁等性能瓶颈 Goroutine Profiling:报告 goroutines 的使用情况,有哪些 goroutine,它们的调用关系是怎样的 go 提供了: runtime/pprof,适合一次性运行的程序 net/http/pprof,web服务型的使用 服务应用型 import _ "net/http/pprof" 结果 flat:给定函数上运行耗时 flat%:同上的 CPU 运行耗时总比例 sum%:给定函数累积使用 CPU 总比例 cum:当前函数加上它之上的调用运行总耗时 cum%:同上的 CPU 运行耗时总比例 参考 使用 pprof 和火焰图调试 golang 应用 Tutorial for optimizing golang program
交叉编译 Golang 交叉编译与选择性编译 树莓派cmd CGO_ENABLED=0 GOOS=linux GOARCH=arm go build xxx.go 问题 如果依赖库使用了如C、C++,那么交叉编译的时候是需要打开CGO_ENABLED=1,并制定CC参数(cross compiler) 这里以macos darwin为例,我要在mac上写好代码,要编译后调试逻辑 使用docker放到对应环境中编译,需要安装docker,建议,避免环境不一致的问题 docker run --rm -v `pwd`:/code golang:1.18-rc bash -c "ls /code && ls /code/deploy && cd /code && /usr/local/go/bin/go build -o /code/deploy/20220905235741/yogo ./"` 使用macos-cross-toolchains brew tap messense/macos-cross-toolchains # install x86_64-unknown-linux-gnu toolchain brew install x86_64-unknown-linux-gnu # install aarch64-unknown-linux-gnu toolchain brew install aarch64-unknown-linux-gnu # build GOOS=linux GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-unknown-linux-gnu-gcc go build 使用musl(类似glibc),需要运行环境安装musl库,如apt install musl,否则会提示no such file brew install FiloSottile/musl-cross/musl-cross GOOS=linux GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-linux-musl-gcc go build