记一些工作常用的工具包函数——golang

记一些工作常用的工具包函数——golang

流星aday
2021-10-27 / 0 评论 / 112 阅读 / 正在检测是否收录...
//ReverseString 反转字符串
func ReverseString(s string) string {
    runes := []rune(s)
    for from, to := 0, len(runes)-1; from < to; from, to = from+1, to-1 {
        runes[from], runes[to] = runes[to], runes[from]
    }
    return string(runes)
}

//Exists 判断文件存在
func Exists(path string) bool {
    _, e := os.Stat(path)
    return e == nil || os.IsExist(e)
}

//ShellExec 运行命令
func ShellExec(command string, arg ...string) (string, error) {
    var builder strings.Builder
    _, _ = builder.WriteString(command)
    for _, v := range arg {
        _, _ = builder.WriteString(" ")
        _, _ = builder.WriteString(v)
    }
    stdOut, stdErr, e := RunCmdAndGetOutput(exec.Command("/bin/bash", "-c", builder.String()))
    if e != nil {
        e = errors.New(stdErr)
    }
    return stdOut, e
}

//ShellExecBackends 后台运行命令
func ShellExecBackends(command string, arg ...string) error {
    var builder strings.Builder
    _, _ = builder.WriteString(command)
    for _, v := range arg {
        _, _ = builder.WriteString(" ")
        _, _ = builder.WriteString(v)
    }
    cmd := exec.Command("/bin/bash", "-c", builder.String())
    if e := cmd.Start(); e != nil {
        return gerror.Wrap(e, "ShellExecBackends")
    }
    go cmd.Wait() //避免僵尸进程
    return nil
}

//PostFormRequest post表单请求,超时30s
//url 请求api
//data 数据
//ssl 是否关闭ssl,true关闭
func PostFormRequest(url string, data url.Values, ssl bool) ([]byte, error) {
    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: ssl},
        },
    }
    client.Timeout = time.Second * 30
    form, err := client.PostForm(url, data)
    if err != nil {
        return nil, gerror.Wrap(err, "PostFormRequest")
    }
    defer form.Body.Close()
    res, err := io.ReadAll(form.Body)
    if err != nil {
        return nil, gerror.Wrap(err, "PostFormRequest1")
    }
    return res, nil
}

//GetRequest get请求
//url 请求api
//header 请求头
//ssl 是否关闭ssl,true关闭
func GetRequest(url string, header http.Header, ssl bool) ([]byte, error) {
    request, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return nil, gerror.Wrap(err, "GetRequest")
    }
    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{InsecureSkipVerify: ssl},
        },
    }
    request.Header = header
    response, err := client.Do(request)
    if err != nil {
        return nil, gerror.Wrap(err, "GetRequest1")
    }
    defer response.Body.Close()
    res, err := io.ReadAll(response.Body)
    if err != nil {
        return nil, gerror.Wrap(err, "GetRequest2")
    }
    return res, nil
}

//GetStringMd5 计算字符串md5
func GetStringMd5(str string) string {
    h := md5.New()
    _, _ = h.Write([]byte(str))
    return hex.EncodeToString(h.Sum(nil))
}

//GetFileMd5 计算文件md5
func GetFileMd5(file string) (string, error) {
    f, err := os.Open(file)
    if err != nil {
        return "", err
    }
    defer f.Close()
    hash := md5.New()
    if _, err = io.Copy(hash, f); err != nil {
        return "", err
    }
    return hex.EncodeToString(hash.Sum(nil)[:16]), nil
}

//WatchFile 监听文件修改
func WatchFile(file string, fn func()) {
    //创建一个监控对象
    watcher, err := fsnotify.NewWatcher()
    if err != nil {
        logrus.Warning("WatchFile:", err)
        return
    }
    if err = watcher.Add(file); err != nil {
        logrus.Warning("WatchFile1:", err)
        return
    }
    //启动一个协和监听config是否被修改
    go func() {
        ch := make(chan os.Signal, 1)
        signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
        <-ch
        _ = watcher.Close()
    }()
    //另启一个goroutine来处理监控对象的事件
    go func() {
        for {
            select {
            case event, ok := <-watcher.Events:
                if !ok {
                    return
                }
                if event.Op&fsnotify.Write == fsnotify.Write {
                    fn()
                }
            case err, ok := <-watcher.Errors:
                if !ok {
                    return
                }
                logrus.Warning("WatchFile2:", err)
            }
        }
    }()
}

//SwitchUserRight 切换到指定用户权限(用户及组)仅对文件操作生效,会影响当前协程的向下执行逻辑及所有子函数
//切换时注意需权限控制的异步io是否运行完毕,否则可能会才出现权限问题
//name 为空则切换回程序执行用户
func SwitchUserRight(name ...string) error {
    var uid, gid int
    var userInfo *user.User
    if len(name) == 0 {
        u, e := user.Current()
        if e != nil {
            return gerror.Wrap(e, "SwitchUserRight1")
        }
        userInfo = u
    } else {
        u, e := user.Lookup(name[0])
        if e != nil {
            return gerror.Wrap(e, "SwitchUserRight2")
        }
        userInfo = u
    }
    gid, e := strconv.Atoi(userInfo.Gid)
    if e != nil {
        return gerror.Wrap(e, "SwitchUserRight3")
    }
    uid, e = strconv.Atoi(userInfo.Uid)
    if e != nil {
        return gerror.Wrap(e, "SwitchUserRight4")
    }
    if e = syscall.Setfsgid(gid); e != nil {
        return gerror.Wrap(e, "conversion failure1")
    }
    if e = syscall.Setfsuid(uid); e != nil {
        return gerror.Wrap(e, "conversion failure2")
    }
    return nil
}

//CheckPort 检测端口是否占用
//return true被占用 false未被占用
func CheckPort(port uint16) (bool, error) {
    conn, err := net.DialTimeout("tcp", fmt.Sprintf("0.0.0.0:%d", port), 3*time.Second)
    if err != nil {
        return false, nil
    }
    _ = conn.Close()
    return true, nil
}

func main() {
//接收参数
    daemon := flag.Bool("D", false, "Run in daemon mode")
    flag.Parse()

    //后台运行
    if *daemon && os.Getppid() != 1 {
        //判断当其是否是子进程,当父进程return之后,子进程会被系统1号进程接管
        filePath, err := filepath.Abs(os.Args[0])
        if err != nil {
            log.Fatalln(err)
        }
        cmd := exec.Command(filePath)
        cmd.Stdin = nil
        cmd.Stdout = nil
        cmd.Stderr = nil
        if err = cmd.Start(); err != nil {
            log.Fatalln(err)
        }
        return
    }

    //监听进程信号,优雅退出
    go func() {
        ch := make(chan os.Signal, 1)
        signal.Notify(ch, unix.SIGINT, unix.SIGTERM, unix.SIGQUIT, unix.SIGHUP)
        <-ch
        os.Exit(0)
    }()

}

//FileSizeFriendly 文件大小人性化
//size单位B
func FileSizeFriendly(size int64) string {
    if size < 1024 {
        return fmt.Sprintf("%.2fB", float64(size))
    }
    if size < (1024 * 1024) {
        return fmt.Sprintf("%.2fKB", float64(size)/float64(1024))
    }
    if size < (1024 * 1024 * 1024) {
        return fmt.Sprintf("%.2fMB", float64(size)/float64(1024*1024))
    }
    if size < (1024 * 1024 * 1024 * 1024) {
        return fmt.Sprintf("%.2fGB", float64(size)/float64(1024*1024*1024))
    }
    if size < (1024 * 1024 * 1024 * 1024 * 1024) {
        return fmt.Sprintf("%.2fTB", float64(size)/float64(1024*1024*1024*1024))
    }
    return fmt.Sprintf("%.2fEB", float64(size)/float64(1024*1024*1024*1024*1024))
}
4

评论

博主关闭了所有页面的评论