golang笔记
关于golang.org无法连接
虽然推荐使用
1go get -u golang.org/x/sync
但很不幸,国内无法连接golang.org,所以只能曲线救国,借助github.com来安装相关的package
1git clone https://github.com/golang/sync ./ 2# 或者 3git clone https://github.com/golang/sync 4mv sync $GOPATH/src/golang/x/
初始化Gopkg
1# go mod init jlb 2go: copying requirements from Gopkg.lock 3go: converting Gopkg.lock: stat google.golang.org/genproto@a8101f21cf983e773d0c1133ebc5424792003214: unrecognized import path "google.golang.org/genproto": https fetch: Get "https://google.golang.org/genproto?go-get=1": dial tcp 216.239.37.1:443: i/o timeout
GORPOXY只适用于go mod
需要先移动Gopkg.lock
1mv Gopkg.lock Gopkg.lock.bak
然后执行
1go mod init jlb 2go mod tidy
读取配置文件
注: Configuration 里元素(Path)必须大写开头
1import ( 2 "encoding/json" 3 "flag" 4 "fmt" 5 "io/ioutil" 6) 7 8type Configuration struct { 9 Path string 10} 11 12const VETSION = "0.1.0" 13 14var ( 15 config Configuration 16) 17 18func init() { 19 var ( 20 conf_file string 21 print_ver bool 22 ) 23 flag.StringVar(&conf_file, "c", "etc/config.json", "config file") 24 flag.BoolVar(&print_ver, "v", false, "config file") 25 flag.Parse() 26 27 raw, err := ioutil.ReadFile(conf_file) 28 if err != nil { 29 log.Error("config parse fail!") 30 os.Exit(1) 31 } 32 err = json.Unmarshal(raw, &config) 33 if err != nil { 34 log.Error("config unmarshal fail!") 35 os.Exit(1) 36 } 37 if print_ver { 38 fmt.Println("version:", VERSION) 39 os.Exit(0) 40 } 41}
判断文件是否存在
1import ( 2 "os" 3) 4func file_is_exists(f string) bool { 5 _, err := os.Stat(f) 6 if os.IsNotExist(err) { 7 return false 8 } 9 return err == nil 10}
随机睡眠
1import ( 2 "math/rand" 3 "time" 4) 5func random_sleep(t int) { 6 rand.Seed(time.Now().Unix()) 7 time.Sleep(time.Duration(rand.Intn(t)) * time.Microsecond) 8}
字符串
随机的n位字符串
1var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 2 3func randStringRunes(n int) string { 4 rand.Seed(time.Now().UnixNano()) 5 b := make([]rune, n) 6 for i := range b { 7 b[i] = letterRunes[rand.Intn(len(letterRunes))] 8 } 9 return string(b) 10}
字符串连接
1import ( 2 "bytes" 3) 4func string_concat(s ...string) string { 5 var buffer bytes.Buffer 6 for _, i := range s { 7 buffer.WriteString(i) 8 } 9 return buffer.String() 10}
打印原始字符(换行符)
1import ( 2 "bytes" 3) 4func print_text(s) string { 5 fmt.Printf("%#v\n", s) 6}
检查元素是否在map中
1func check_in_map(f map[string]string, v string) bool { 2 if _, ok := f[v]; ok { 3 return true 4 } 5 return false 6}
检查元素是否在list中
1func check_in_list(f []string, v string) bool { 2 for i := range f { 3 if f[i] == v { 4 return true 5 } 6 } 7 return false 8}
执行Linux命令
1import ( 2 "os/exec" 3) 4func exec_command(command string, args ...string) (error, bool) { 5 var ( 6 err error 7 ) 8 cmd := exec.Command(command, args...) 9 cmd.Start() 10 done := make(chan error) 11 go func() { 12 done <- cmd.Wait() 13 }() 14 15 select { 16 case <-time.After(600 * time.Second): 17 if err = cmd.Process.Kill(); err != nil { 18 log.Error("failed to kill: %s, error: %s", cmd.Path, err) 19 } 20 go func() { 21 <-done // allow goroutine to exit 22 }() 23 log.Info("process:%s killed", cmd.Path) 24 return err, true 25 case err = <-done: 26 return err, false 27 } 28}
迭代文件目录
1func file_iter(path string) []string { 2 // path must be abs path 3 var files []string 4 scripts, _ := ioutil.ReadDir(path) 5 for _, script := range scripts { 6 if script.IsDir() { 7 return file_iter(filepath.Join(path, script.Name())) 8 } 9 files = append(files, filepath.Join(path, script.Name())) 10 } 11 return files 12}
求两列表的差集
1func difference(a,b []string) []string { 2 // len(a) < len(b), avoid all item of a belong to b 3 m := map[string]bool{} 4 for _, x := range a { 5 m[x] = true 6 } 7 diff := []string{} 8 for _, x := range b { 9 if _, ok := m[x]; !ok { 10 diff = append(diff, x) 11 } 12 } 13 return diff 14}
删除列表中重复的数据
1func RemoveDuplicates(elements []string) []string { 2 keys := map[string]bool{} 3 result := []string{} 4 5 for _, element := range elements { 6 if _, value := keys[element]; !value { 7 keys[element] = true 8 result = append(result, element) 9 } 10 } 11 return result 12}
参数校验
是否是IP
1func IsValidIP(key string) bool { 2 IP := net.ParseIP(key) 3 if IP == nil { 4 return false 5 } 6 7 return true 8}
是否是EMAIL
1import "regexp" 2 3func IsValidEmail(key string) bool { 4 re := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") 5 if !re.MatchString(key) { 6 return false 7 } 8 if strings.HasSuffix(key, "@upai.com") || strings.HasSuffix(key, "@huaban.com") { 9 return true 10 } 11 return false 12}
读取http响应的gz package
1func main() { 2 resp, _ := HTTPRequest("GET", "http://some-gz-package/package-name", nil) 3 defer resp.Body.Close() 4 5 gz, err := gzip.NewReader(resp.Body) 6 if err != nil { 7 fmt.Println(err.Error()) 8 return 9 } 10 defer gz.Close() 11 scanner := bufio.NewScanner(gz) 12 for scanner.Scan() { 13 fmt.Println(scanner.Text()) 14 } 15}
编译
编译成不同系统的可执行文件
-
GOOS:目标可执行程序运行操作系统,支持 darwin,freebsd,linux,windows
-
GOARCH:目标可执行程序操作系统构架,包括 386,amd64,arm
1# Golang version 1.5以前版本在首次交叉编译时还需要配置交叉编译环境: 2CGO_ENABLED=0 GOOS=linux GOARCH=amd64 ./make.bash 3CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash
-
Mac下编译Linux, Windows平台的64位可执行程序:
1$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build test.go 2$ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go
-
Linux下编译Mac, Windows平台的64位可执行程序:
1$ CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build test.go 2$ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go
-
Windows下编译Mac, Linux平台的64位可执行程序:
1$ SET CGO_ENABLED=0SET GOOS=darwin3 SET GOARCH=amd64 go build test.go 2$ SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build test.go
测试
指定函数
-
test
1go test -run="^TestAAA" ./... -
bench
1go test -bench="^BenchmarkAAA" -run="^Benchmark" ./...
常见问题
docker内运行时区问题
解决方式
1apt-get install -y tzdata
map性能
1只读场景:sync.map > rwmutex >> mutex 2读写场景(边读边写):rwmutex > mutex >> sync.map 3读写场景(读80% 写20%):sync.map > rwmutex > mutex 4读写场景(读98% 写2%):sync.map > rwmutex >> mutex 5只写场景:sync.map >> mutex > rwmutex
go mod tidy checking tree against
https://github.com/golang/go/issues/35164
1└──╼ go mod tidy 2go: finding module for package github.com/honmaple/org-golang 3go: finding module for package github.com/honmaple/org-golang/render 4go: downloading github.com/honmaple/org-golang v0.0.0-20230214143528-22f61b3874c8 5github.com/honmaple/snow/builder/page/markup/orgmode imports 6 github.com/honmaple/org-golang: github.com/honmaple/org-golang@v0.0.0-20230214143528-22f61b3874c8: verifying module: github.com/honmaple/org-golang@v0.0.0-20230214143528-22f61b3874c8: checking tree#15584694 against tree#15683659: reading https://goproxy.io/sumdb/sum.golang.org/tile/8/1/237: 404 Not Found 7 server response: not found 8github.com/honmaple/snow/builder/page/markup/orgmode imports 9 github.com/honmaple/org-golang/render: github.com/honmaple/org-golang@v0.0.0-20230214143528-22f61b3874c8: verifying module: github.com/honmaple/org-golang@v0.0.0-20230214143528-22f61b3874c8: checking tree#15584694 against tree#15683659: reading https://goproxy.io/sumdb/sum.golang.org/tile/8/1/237: 404 Not Found 10 server response: not found
1└──╼ GOSUMDB=off go mod tidy 2go: finding module for package github.com/honmaple/org-golang 3go: finding module for package github.com/honmaple/org-golang/render 4go: downloading github.com/honmaple/org-golang v0.0.0-20230214143528-22f61b3874c8 5go: found github.com/honmaple/org-golang in github.com/honmaple/org-golang v0.0.0-20230214143528-22f61b3874c8 6go: found github.com/honmaple/org-golang/render in github.com/honmaple/org-golang v0.0.0-20230214143528-22f61b3874c8
