golang 工程构建基础
golang 工程构建基础
1. 打生产包
- 默认情况打包会增加本地绝对路径,必须去掉本地路径前缀
- 若包不大,为方便起见,可将使用静态本地 glibc,防止跨不同 linux 内核版本无法执行,否则建议分不同 linux 内核版本打包
# 解决不同平台 glibc 兼容问题. 如: ubuntu在/lib/i386-linux-gnu/libc.so.6, centos在/usr/lib64/libc.so
export CGO_LDFLAGS="-Xlinker -rpath=$(whereis libc.so|sed 's/ /\n/g'|grep libc.so) -static"
export CGO_ENABLED=0
export GOOS=linux
export GOARCH=amd64
export BUILD_VERSION=$(git branch | grep '*' | sed -E 's/\* \(HEAD detached at |\)|\* //g')
go build -v -a \
-ldflags '-s -w' \
-ldflags="-s -X 'main.version=${BUILD_VERSION}'" \
-gcflags="all=-trimpath=$(pwd)" \
-asmflags="all=-trimpath=$(pwd)" \
-o $(pwd)/mybinary
2. 基础类型互转
2.1 float、int、int64、string 类型互转
// string => int
int, err: = strconv.Atoi(string)
// string => int64
// 第三个参数位大小表示期望转换的结果类型,其值可以为0, 8, 16, 32和64,分别对应 int, int8, int16, int32和int64
int64, err := strconv.ParseInt(string, 10, 64)
// string => float
float, err := strconv.ParseFloat(string, 64)
float, err := strconv.ParseFloat(string, 32)
// int => string
string := strconv.Itoa(int)
// 等价于 string := strconv.FormatInt(int64(int), 10)
// int64 => string
string := strconv.FormatInt(int64, 10)
// int => int64
int64 := int64(1234)
// float => string
string := strconv.FormatFloat(float32, 'E', -1, 32)
string := strconv.FormatFloat(float64, 'E', -1, 64)
2.2 int32、string 互转
-
编写转换函数(最快)
func String(n int32) string { buf := [11]byte{} pos := len(buf) i := int64(n) signed := i < 0 if signed { i = -i } for { pos-- buf[pos],i = '0'+byte(i%10),i/10 if i == 0 { if signed { pos-- buf[pos] = '-' } return string(buf[pos:]) } } }
-
使用fmt.Sprint(i)(慢)
// Sprint formats using the default formats for its operands and returns the resulting string.
// Spaces are added between operands when neither is a string.
func Sprint(a ...interface{}) string {
p := newPrinter()
p.doPrint(a)
s := string(p.buf)
p.free()
return s
}
- 使用strconv.Itoa(int(i))(快速)
// Itoa is shorthand for FormatInt(int64(i),10).
func Itoa(i int) string {
return FormatInt(int64(i),10)
}
- 使用strconv.FormatInt(int64(i),10)(更快)
// FormatInt returns the string representation of i in the given base,// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
// for digit values >= 10.
func FormatInt(i int64,base int) string {
_,s := formatBits(nil,uint64(i),base,i < 0,false)
return s
}
- 比较&基准测试(具有50000000次迭代):
s = String(i) takes: 5.5923198s
s = String2(i) takes: 5.5923199s
s = strconv.FormatInt(int64(i),10) takes: 5.9133382s
s = strconv.Itoa(int(i)) takes: 5.9763418s
s = fmt.Sprint(i) takes: 13.5697761s
测试代码
package main
import (
"fmt"
//"strconv"
"time"
)
func main() {
var s string
i := int32(-2147483648)
t := time.Now()
for j := 0; j < 50000000; j++ {
s = String(i) //5.5923198s
//s = String2(i) //5.5923199s
//s = strconv.FormatInt(int64(i),10) // 5.9133382s
//s = strconv.Itoa(int(i)) //5.9763418s
//s = fmt.Sprint(i) // 13.5697761s
}
fmt.Println(time.Since(t))
fmt.Println(s)
}
func String(n int32) string {
buf := [11]byte{}
pos := len(buf)
i := int64(n)
signed := i < 0
if signed {
i = -i
}
for {
pos--
buf[pos],i/10
if i == 0 {
if signed {
pos--
buf[pos] = '-'
}
return string(buf[pos:])
}
}
}
func String2(n int32) string {
buf := [11]byte{}
pos := len(buf)
i,q := int64(n),int64(0)
signed := i < 0
if signed {
i = -i
}
for {
pos--
q = i / 10
buf[pos],i = '0'+byte(i-10*q),q
if i == 0 {
if signed {
pos--
buf[pos] = '-'
}
return string(buf[pos:])
}
}
}
3. FAQ
3.1 升级 golang(1.7.3) 后在 VSCode(1.61.0) 中使用 dlv-dap(1.7) debugging 无法进入断点?
-
原因: 首先确保已安装 (Extensions -> 搜索 go) 插件,由于新版 vscode-go 的 dlv-dap 插件重构了,默认就启用了新模式与 Delve 通信以进行本地调试,参见官方排查说明:https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting
-
解决: vscode setting -> go setting 增加如下配置即可:
// ...
// Ignore others configuration ...
// ...
"go.delveConfig": {
"debugAdapter": "legacy",
},
3.2 使用 vscode 开发,以 debug 模式运行突然报错 # command-line-arguments src/demo/main/main.go:4:2: undefined: main.go
,但直接使用 go run main.go
却正常?
-
总结: 该出错原因属于go的多文件加载问题,亲测有效的方法是修改
launch.json
中的程序入口文件如:"program": "${workspaceFolder}/server/main.go",
或"program": "${workspaceFolder}/server/",
两种尝试切换即可,一般使用 package 模式运行就会正常。如果还是不行可尝试重新初始化,即:rm -rf go.sum go.mod; go clean; go mod init; go mod tidy; go mod vendor; go build;
,然后再改launch.json
多试几次一般都会OK。 -
参考 3: How to get the full path and directory of a Makefile itself?
3.3 调试 golang 程序断点处显示 Unverify breakpoint
,然后 launch.json
中增加"trace": "verbose"
后错误日志中显示 Could not found xx/src//xx.go
- 原因是因为 vscode go 插件支持软链目录,打开项目的路径必须是实际路径,参见:https://stackoverflow.com/questions/69660812/cant-debug-golang-with-breakpoints-in-vscode
3.4 dlv版本与golang不兼容,需安装最新
cd $GOROOT/src/$project
go get -v github.com/go-delve/delve/cmd/dlv