Golang
实践
- 尽量避免 cgo
- 重复代码尽量 生成
caution
go get
不会下载源码到~/go/src
了 - #31529- c-shared 不支持 musl - golang/go#13492
- json omitempty 不支持 struct golang/go#11939
-
参考
-
Websocket C10M
Directory and file names that begin with "." or _
are ignored by the go tool, as are directories named "testdata".
# 更新 Go 过后可能会导致每个项目都会重复构建, 导致编译很慢, 针对单个项目可以按照如下的方式处理
# 把所有的依赖从新编译
go build -v 2> /tmp/build-tmp
sed -i '$ d' /tmp/build-tmp
# 更新所有依赖
cat /tmp/build-tmp | xargs -n 1 go get -u -v
# go build -v 2> /tmp/build-tmp;sed -i '$ d' /tmp/build-tmp;cat /tmp/build-tmp | xargs -n 1 go get -u -v
# 重新构建并缓存, 这样下次构建就会很快了
go build -i -v ./...
# 跨平台编译
env GOOS=linux GOARCH=amd64 go build -o main-linux-amd64 main.go
# 移动包
go get github.com/golang/tools/cmd/gomvpkg/main.go
gomvpkg -from github.com/wenerme/before -to github.com/wenerme/after
# 将构建时间添加到生成的内容中
go build -ldflags "-X main.minversion=`date -u +.%Y%m%d.%H%M%S`" service.go
go run -ldflags "-X main.xyz=abc" main.go
go run -ldflags "-X main.build=`date +%Y%m%d.%H%M%S`" main.go
# Guru
go get github.com/golang/tools/cmd/guru/main.go
Install golang under linux
GOVERSION=1.7.3
# 查看可选架构 https://storage.googleapis.com/golang/
# Windows 64 位 https://storage.googleapis.com/golang/go$GOVERSION.windows-amd64.zip
# Windows 32 位 https://storage.googleapis.com/golang/go$GOVERSION.windows-386.zip
wget https://storage.googleapis.com/golang/go$GOVERSION.linux-amd64.tar.gz
# 或者使用代理下载
# https_proxy=socks://127.0.0.1:8888 curl https://storage.googleapis.com/golang/go$GOVERSION.linux-amd64.tar.gz -o go$GOVERSION.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go$GOVERSION.linux-amd64.tar.gz
export GOROOT=/usr/local/go
export PATH=$GOROOT/bin:$PATH
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$PATH
# 或将环境变量放到启动脚本
cd ~
echo 'export GOROOT=/usr/local/go' >> $HOME/.bashrc
echo 'export GOPATH=$HOME/go' >> $HOME/.bashrc
echo 'export PATH=$PATH:$GOROOT/bin:$GOPATH/bin' >> $HOME/.bashrc
source $HOME/.bashrc
UNINSTALL
sudo rm -rf /usr/local/go
与 C 交互操作/Interop with C
go install -buildmode=shared -linkshared std
go install -buildmode=shared -linkshared userownpackage
go build -linkshared yourprogram
Export function
//export SayHello
func SayHello(name string) {
fmt.Printf("Nautilus says: Hello, %s!\n", name)
}
Inline C code
// typedef int (*intFunc) ();
//
// int
// bridge_int_func(intFunc f)
// {
// return f();
// }
//
// int fortytwo()
// {
// return 42;
// }
import "C"
import "fmt"
func main() {
f := C.intFunc(C.fortytwo)
fmt.Println(int(C.bridge_int_func(f)))
// Output: 42
}
Reference
交叉编译/Cross compile
# 编译为 Linux 可执行文件
env GOOS=linux GOARCH=amd64 go build -o RedHat/clbeat -v github.com/wenerme/clbeat
# 编译为 Windows 可执行文件
env GOOS=windows GOARCH=amd64 go build -o main.exe -v
部分需要 linux cgo 编译的可使用 docker 镜像完成
docker run --rm -v $GOPATH:/go -w /go/src/应用包 golang go build -i -v
# 因为是使用 alphie 编译的,因此构建的 docker 中需要添加
# RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
# 需要注意 https://github.com/golang/go/issues/9344
xgo
可使用 xgo 一次性编译多个平台的可执行文件,可使用 xgo 镜像以便于跨平台编译 cgo.
- 查看所有支持的环境 environment
Go & C++
使用 Go 和 C++ 可通过 Swig 实现,也可通过将 C++ 的方法全封装为 C 方法,然后再通过 Go 调用. 在量较少的时候,使用第二种方式是非常方便快捷的,但是如果想要把大量的接口导出到 Go, 并且保持类特性,则只能使用 Swig.
Go 自 1.1 开就支持 Swig 了.
# 相关帮助
swig -go -help
swig -go -intgosize 64 -c++ -cgo director.i
go install
swig -go --help
Go Options (available with -go)
-cgo - Generate cgo input files
-gccgo - Generate code for gccgo rather than 6g/8g
-go-pkgpath <p> - Like gccgo -fgo-pkgpath option
-go-prefix <p> - Like gccgo -fgo-prefix option
-intgosize <s> - Set size of Go int type--32 or 64 bits
-package <name> - Set name of the Go package to <name>
-use-shlib - Force use of a shared library
-soname <name> - Set shared library holding C/C++ code to <name>
程序瘦身/Reduce binary size
# A Hello world in Golang 1.6 is 2.2M
# 2.1M
strip main
# -s disable symbol table
# -w disable DWARF generation
# 1.7M
go build -ldflags "-s -w" main.go
# UPX can not compress drawin.amd64
env GOOS=linux GOARCH=amd64 go build -o main.linux.amd64 main.go # 2.2M
env GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" -o main.linux.amd64.flag main.go # 1.6M
upx --best main.linux.amd64 # 666K
upx -9 --ultra-brute main.linux.amd64 # 508K
upx --best main.linux.amd64 # 478K
upx -9 --ultra-brute main.linux.amd64 # 363K
Profiling
https://blog.golang.org/profiling-go-programs https://golang.org/pkg/net/http/pprof/
Beego
go get -u github.com/beego/bee
go get -u github.com/astaxie/beego
bee api bapi
cd bapi
bee run -downdoc=true -gendoc=true
Self Update
参考/Reference
- Articles
- Video
- cmd/go
- vender
- Summary of Go Generics Discussions
- FAQ
- The Three Go Landmines
- pkg/plugin
- Calling Go Functions from Other Languages
学习资源
- 《Go 编程基础》 是一套针对 Google 出品的 Go 语言的视频语音教程,主要面向新手级别的学习者。
- Learning-Go
- Go Web 基础
- Go 名库讲解
- Go 语言学习资料与社区索引
FAQ
什么时候使用指针
- 方法接收使用指针
- 当有疑问时, 使用指针
- 当结构体比较大, 或会发生变化时使用指针
为枚举生成 String 方法
- 使用 Stringer 生成
- 生成的默认文件为
<type>_string.go
// 为类型 MyType 生成 Stringer
//go:generate stringer -type=MyType
// 输出到 strings.go
//go:generate stringer -type=MyType -output=strings.go