golang笔记


关于golang.org无法连接

虽然推荐使用

go get -u golang.org/x/sync

但很不幸,国内无法连接golang.org,所以只能曲线救国,借助github.com来安装相关的package

git clone https://github.com/golang/sync ./
# 或者
git clone https://github.com/golang/sync
mv sync $GOPATH/src/golang/x/

初始化Gopkg

# go mod init jlb
go: copying requirements from Gopkg.lock
go: 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

mv Gopkg.lock Gopkg.lock.bak

然后执行

go mod init jlb
go mod tidy

读取配置文件

注: Configuration 里元素(Path)必须大写开头

import (
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
)

type Configuration struct {
    Path string
}

const VETSION = "0.1.0"

var (
    config Configuration
)

func init() {
    var (
        conf_file string
        print_ver bool
    )
    flag.StringVar(&conf_file, "c", "etc/config.json", "config file")
    flag.BoolVar(&print_ver, "v", false, "config file")
    flag.Parse()

    raw, err := ioutil.ReadFile(conf_file)
    if err != nil {
        log.Error("config parse fail!")
        os.Exit(1)
    }
    err = json.Unmarshal(raw, &config)
    if err != nil {
        log.Error("config unmarshal fail!")
        os.Exit(1)
    }
    if print_ver {
        fmt.Println("version:", VERSION)
        os.Exit(0)
    }
}

判断文件是否存在

import (
    "os"
)
func file_is_exists(f string) bool {
    _, err := os.Stat(f)
    if os.IsNotExist(err) {
        return false
    }
    return err == nil
}

随机睡眠

import (
    "math/rand"
    "time"
)
func random_sleep(t int) {
    rand.Seed(time.Now().Unix())
    time.Sleep(time.Duration(rand.Intn(t)) * time.Microsecond)
}

字符串

随机的n位字符串

var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randStringRunes(n int) string {
    rand.Seed(time.Now().UnixNano())
    b := make([]rune, n)
    for i := range b {
        b[i] = letterRunes[rand.Intn(len(letterRunes))]
    }
    return string(b)
}

字符串连接

import (
    "bytes"
)
func string_concat(s ...string) string {
    var buffer bytes.Buffer
    for _, i := range s {
        buffer.WriteString(i)
    }
    return buffer.String()
}

打印原始字符(换行符)

import (
    "bytes"
)
func print_text(s) string {
    fmt.Printf("%#v\n", s)
}

检查元素是否在map中

func check_in_map(f map[string]string, v string) bool {
    if _, ok := f[v]; ok {
        return true
    }
    return false
}

检查元素是否在list中

func check_in_list(f []string, v string) bool {
    for i := range f {
        if f[i] == v {
            return true
        }
    }
    return false
}

执行Linux命令

import (
    "os/exec"
)
func exec_command(command string, args ...string) (error, bool) {
    var (
        err error
    )
    cmd := exec.Command(command, args...)
    cmd.Start()
    done := make(chan error)
    go func() {
        done <- cmd.Wait()
    }()

    select {
    case <-time.After(600 * time.Second):
        if err = cmd.Process.Kill(); err != nil {
            log.Error("failed to kill: %s, error: %s", cmd.Path, err)
        }
        go func() {
            <-done // allow goroutine to exit
        }()
        log.Info("process:%s killed", cmd.Path)
        return err, true
    case err = <-done:
        return err, false
    }
}

迭代文件目录

func file_iter(path string) []string {
    // path must be abs path
    var files []string
    scripts, _ := ioutil.ReadDir(path)
    for _, script := range scripts {
        if script.IsDir() {
            return file_iter(filepath.Join(path, script.Name()))
        }
        files = append(files, filepath.Join(path, script.Name()))
    }
    return files
}

求两列表的差集

func difference(a,b []string) []string {
    // len(a) < len(b), avoid all item of a belong to b
    m := map[string]bool{}
    for _, x := range a {
        m[x] = true
    }
    diff := []string{}
    for _, x := range b {
        if _, ok := m[x]; !ok {
            diff = append(diff, x)
        }
    }
    return diff
}

删除列表中重复的数据

func RemoveDuplicates(elements []string) []string {
    keys := map[string]bool{}
    result := []string{}

    for _, element := range elements {
        if _, value := keys[element]; !value {
            keys[element] = true
            result = append(result, element)
        }
    }
    return result
}

参数校验

是否是IP

func IsValidIP(key string) bool {
    IP := net.ParseIP(key)
    if IP == nil {
        return false
    }

    return true
}

是否是EMAIL

import "regexp"

func IsValidEmail(key string) bool {
    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])?)*$")
    if !re.MatchString(key) {
        return false
    }
    if strings.HasSuffix(key, "@upai.com") || strings.HasSuffix(key, "@huaban.com") {
        return true
    }
    return false
}

读取http响应的gz package

func main() {
    resp, _ := HTTPRequest("GET", "http://some-gz-package/package-name", nil)
    defer resp.Body.Close()

    gz, err := gzip.NewReader(resp.Body)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    defer gz.Close()
    scanner := bufio.NewScanner(gz)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}

编译

编译成不同系统的可执行文件

  • GOOS:目标可执行程序运行操作系统,支持 darwin,freebsd,linux,windows

  • GOARCH:目标可执行程序操作系统构架,包括 386,amd64,arm

    # Golang version 1.5以前版本在首次交叉编译时还需要配置交叉编译环境:
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 ./make.bash
    CGO_ENABLED=0 GOOS=windows GOARCH=amd64 ./make.bash
  1. Mac下编译Linux, Windows平台的64位可执行程序:

    $ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build test.go
    $ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go
  2. Linux下编译Mac, Windows平台的64位可执行程序:

    $ CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build test.go
    $ CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build test.go
  3. Windows下编译Mac, Linux平台的64位可执行程序:

    $ SET CGO_ENABLED=0SET GOOS=darwin3 SET GOARCH=amd64 go build test.go
    $ SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build test.go

测试

指定函数

  • test

    go test -run="^TestAAA" ./...
  • bench

    go test -bench="^BenchmarkAAA" -run="^Benchmark" ./...

常见问题

docker内运行时区问题

解决方式

apt-get install -y tzdata

map性能

只读场景:sync.map > rwmutex >> mutex
读写场景(边读边写):rwmutex > mutex >> sync.map
读写场景(读80% 写20%):sync.map > rwmutex > mutex
读写场景(读98% 写2%):sync.map > rwmutex >> mutex
只写场景:sync.map >> mutex > rwmutex

go mod tidy checking tree against

https://github.com/golang/go/issues/35164

 go mod tidy
go: finding module for package github.com/honmaple/org-golang
go: finding module for package github.com/honmaple/org-golang/render
go: downloading github.com/honmaple/org-golang v0.0.0-20230214143528-22f61b3874c8
github.com/honmaple/snow/builder/page/markup/orgmode imports
    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
    server response: not found
github.com/honmaple/snow/builder/page/markup/orgmode imports
    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
    server response: not found
 GOSUMDB=off go mod tidy
go: finding module for package github.com/honmaple/org-golang
go: finding module for package github.com/honmaple/org-golang/render
go: downloading github.com/honmaple/org-golang v0.0.0-20230214143528-22f61b3874c8
go: found github.com/honmaple/org-golang in github.com/honmaple/org-golang v0.0.0-20230214143528-22f61b3874c8
go: found github.com/honmaple/org-golang/render in github.com/honmaple/org-golang v0.0.0-20230214143528-22f61b3874c8
作者: honmaple
链接: https://honmaple.me/articles/2018/03/golang笔记.html
版权: CC BY-NC-SA 4.0 知识共享署名-非商业性使用-相同方式共享4.0国际许可协议
wechat
alipay

加载评论