1. GOPROXY 配置
因为众所周知的原因,通过 go get
下载代码模块会非常慢,甚至连接失败。此时需要配置代理。
可以参考 Goproxy 中国,配置:
shell
go env -w GOPROXY=https://goproxy.cn,direct
该操作会向 Go 的配置文件中写入相关配置,可以通过 go env GOENV
查看配置文件路径。
2. GOPRIVATE 配置
有些模块是私有的,例如企业内部的私有代码仓库。此时 go get
无法直接下载,需要配置 GOPRIVATE
环境变量,例如:
shell
go env -w GOPRIVATE="*.my-corp.com"
可以通过 go help module-private
查看更多信息。
通常,该配置需要结合 Git 的另外一个配置来使用:
shell
git config --global url."git@git.my-corp.com:".insteadOf "https://git.my-corp.com/"
即,在下载私有模块的时候默认使用 git 协议。
3. string 和 []byte 互相转换
最简单的:
go
package main
import (
"fmt"
)
func main() {
s := "hello"
fmt.Println([]byte(s))
// [104 101 108 108 111]
b := []byte{'h', 'e', 'l', 'l', 'o'}
fmt.Println(string(b))
// hello
}
另外一种无须额外分配内存的方式为:
go
package main
import (
"fmt"
"reflect"
"unsafe"
)
// StringToBytes converts string to byte slice without a memory allocation.
func StringToBytes(s string) (b []byte) {
sh := *(*reflect.StringHeader)(unsafe.Pointer(&s))
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
bh.Data, bh.Len, bh.Cap = sh.Data, sh.Len, sh.Len
return b
}
// BytesToString converts byte slice to string without a memory allocation.
func BytesToString(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}
func main() {
s := "hello"
fmt.Println(StringToBytes(s))
// [104 101 108 108 111]
b := []byte{'h', 'e', 'l', 'l', 'o'}
fmt.Println(BytesToString(b))
// hello
}
参考 https://github.com/gin-gonic/gin/blob/master/internal/bytesconv/bytesconv.go
4. recover 错误处理
go
package main
import (
"errors"
"fmt"
)
func main() {
defer func() {
if r := recover(); r != nil {
var err error
switch x := r.(type) {
case string:
err = errors.New(x)
case error:
err = x
default:
err = errors.New("unknow error")
}
fmt.Printf("err: %v", err)
}
}()
panic("hello")
}
更多内容参考 Defer, Panic, and Recover
5. 自定义 JSON 序列化方法
例如如下配置:
json
{
"env": "test",
"interval": "10s"
}
希望能够和如下 struct 对应:
go
type Config struct {
Env string `json:"env"`
Interval time.Duration `json:"interval"`
}
比较不优雅的做法是手动去将 interval 在 string 和 time.Duration 类型之间进行转换,但是这样实在不方便,更好的做法是自定义序列化方法。参考如下:
go
package main
import (
"encoding/json"
"fmt"
"time"
)
type Duration time.Duration
func (d Duration) MarshalJSON() ([]byte, error) {
s := fmt.Sprintf("%q", time.Duration(d).String())
return []byte(s), nil
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
t, err := time.ParseDuration(s)
if err != nil {
return err
}
*d = Duration(t)
return nil
}
type Config struct {
Env string `json:"env"`
Interval Duration `json:"interval"`
}
func main() {
c := Config{
Env: "test",
Interval: Duration(time.Second * 10),
}
b, _ := json.Marshal(c)
fmt.Println(string(b))
// {"env":"test","interval":"10s"}
s := `{"env":"dev","interval":"2m"}`
var conf Config
json.Unmarshal([]byte(s), &conf)
fmt.Println(conf)
// {dev 120000000000}
}