标签 golang 下的文章

golang复制文件夹和文件



// File copies a single file from src to dst
func File(src, dst string) error {
    var err error
    var srcfd *os.File
    var dstfd *os.File
    var srcinfo os.FileInfo

    if srcfd, err = os.Open(src); err != nil {
        return err
    }
    defer srcfd.Close()

    if dstfd, err = os.Create(dst); err != nil {
        return err
    }
    defer dstfd.Close()

    if _, err = io.Copy(dstfd, srcfd); err != nil {
        return err
    }
    if srcinfo, err = os.Stat(src); err != nil {
        return err
    }
    return os.Chmod(dst, srcinfo.Mode())
}

// CopyDir copies a whole directory recursively
func CopyDir(src string, dst string) error {
    var err error
    var fds []os.FileInfo
    var srcinfo os.FileInfo

    if srcinfo, err = os.Stat(src); err != nil {
        return err
    }

    if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
        return err
    }

    if fds, err = ioutil.ReadDir(src); err != nil {
        return err
    }
    for _, fd := range fds {
        srcfp := path.Join(src, fd.Name())
        dstfp := path.Join(dst, fd.Name())

        if fd.IsDir() {
            if err = CopyDir(srcfp, dstfp); err != nil {
                fmt.Println(err)
            }
        } else {
            if err = File(srcfp, dstfp); err != nil {
                fmt.Println(err)
            }
        }
    }
    return nil
}


golang给图片添加图片水印



//一个图片添加水印
func SetSY(logo, tp string) {
    //原始图片是sam.jpg
    imgb, err := os.Open(tp)
    if err != nil {
        fmt.Println("打开图片失败")
        return
    }
    img, format1, err := image.Decode(imgb)
    if err != nil {
        fmt.Println("解码图片失败-", format1, err.Error())
        return
    }
    defer imgb.Close()

    wmb, err := os.Open(logo)
    if err != nil {
        fmt.Println("打开Logo失败")
        return
    }
    watermark, format2, err := image.Decode(wmb)
    if err != nil {
        fmt.Println("解码Logo失败-", format2, err.Error())
        return
    }

    defer wmb.Close()

    //把水印写到右下角,并向0坐标各偏移10个像素
    offset := image.Pt(img.Bounds().Dx()-watermark.Bounds().Dx()-10, img.Bounds().Dy()-watermark.Bounds().Dy()-10)
    b := img.Bounds()
    m := image.NewNRGBA(b)

    draw.Draw(m, b, img, image.ZP, draw.Src)
    draw.Draw(m, watermark.Bounds().Add(offset), watermark, image.ZP, draw.Over)

    //生成新图片new.jpg,并设置图片质量..
    imgw, _ := os.Create(tp)
    jpeg.Encode(imgw, m, &jpeg.Options{100})

    defer imgw.Close()

    fmt.Println("添加水印成功...")
}

windows创建文件夹时不能包含一些特殊符号


QQ图片20200922181733.png

Go中使用字符串替换即可

//文件夹不能包含 \ / : * ? " < > |
dirName = strings.Replace(dirName, "\\", "", -1)
dirName = strings.Replace(dirName, "/", "", -1)
dirName = strings.Replace(dirName, ":", "", -1)
dirName = strings.Replace(dirName, "*", "", -1)
dirName = strings.Replace(dirName, "?", "", -1)
dirName = strings.Replace(dirName, "\"", "", -1)
dirName = strings.Replace(dirName, "<", "", -1)
dirName = strings.Replace(dirName, ">", "", -1)
dirName = strings.Replace(dirName, "|", "", -1)

golang 怎么获取url中的host | 怎么判断是否是http



package main

import (
    "fmt"
    "net/url"
    "strings"

    "github.com/asaskevich/govalidator"
)

func main() {
    rawUrl := "https://www.52bd.net/?data=111"
    changeHost := "192.168.1.1"

    if strings.Index(rawUrl, "http://") != -1 || strings.Index(rawUrl, "https://") != -1 {
        fmt.Println("是http协议")
    } else {
        fmt.Println("不是http协议")
    }

    newUrl, _ := url.Parse(rawUrl)

    // Host
    newUrlHost := newUrl.Hostname()
    // Port
    newUrlPort := newUrl.Port()
    // Path
    newUrlPath := newUrl.Path
    // URL类型转string
    stringUrl := newUrl.String()
    // 修改URl Host
    newUrl.Host = changeHost + ":900" + newUrl.Port()

    fmt.Printf("host:%s  端口:%s  path:%s  url:%s newUrl:%s  %v", newUrlHost, newUrlPort, newUrlPath, stringUrl, newUrl, govalidator.IsURL(rawUrl))
    
}


golang jwt鉴权


package model

import (
    "fmt"
    "time"

    jwt "github.com/dgrijalva/jwt-go"
)

const (
    KEY                    string = "JWT-ARY-STARK"
    DEFAULT_EXPIRE_SECONDS int    = 100000 // default 10 minutes
)

// JWT -- json web token
// HEADER PAYLOAD SIGNATURE
// This struct is the PAYLOAD
type MyCustomClaims struct {
    LpUser
    jwt.StandardClaims
}

// update expireAt and return a new token更新expireAt并返回新令牌
func RefreshToken(tokenString string) (string, error) {
    // first get previous token
    token, err := jwt.ParseWithClaims(
        tokenString,
        &MyCustomClaims{},
        func(token *jwt.Token) (interface{}, error) {
            return []byte(KEY), nil
        })
    claims, ok := token.Claims.(*MyCustomClaims)
    if !ok || !token.Valid {
        return "", err
    }
    mySigningKey := []byte(KEY)
    expireAt := time.Now().Add(time.Second * time.Duration(DEFAULT_EXPIRE_SECONDS)).Unix()
    newClaims := MyCustomClaims{
        claims.LpUser,
        jwt.StandardClaims{
            ExpiresAt: expireAt,
            Issuer:    claims.LpUser.Email,
            IssuedAt:  time.Now().Unix(),
        },
    }
    // generate new token with new claims生成带有新声明的新令牌
    newToken := jwt.NewWithClaims(jwt.SigningMethodHS256, newClaims)
    tokenStr, err := newToken.SignedString(mySigningKey)
    if err != nil {
        fmt.Println("generate new fresh json web token failed !! error :", err)
        return "", err
    }
    return tokenStr, err
}

//验证令牌
func ValidateToken(tokenString string) error {
    token, err := jwt.ParseWithClaims(
        tokenString,
        &MyCustomClaims{},
        func(token *jwt.Token) (interface{}, error) {
            return []byte(KEY), nil
        })
    if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
        fmt.Printf("%v %v", claims.LpUser, claims.StandardClaims.ExpiresAt)
        fmt.Println("token will be expired at ", time.Unix(claims.StandardClaims.ExpiresAt, 0))
    } else {
        fmt.Println("validate tokenString failed !!!", err)
        return err
    }
    return nil
}

//生成令牌
func GenerateToken(user LpUser, expiredSeconds int) (tokenString string) {
    if expiredSeconds == 0 {
        expiredSeconds = DEFAULT_EXPIRE_SECONDS
    }
    // Create the Claims
    mySigningKey := []byte(KEY)
    expireAt := time.Now().Add(time.Second * time.Duration(expiredSeconds)).Unix()
    fmt.Println("token will be expired at ", time.Unix(expireAt, 0))
    // pass parameter to this func or not
    claims := MyCustomClaims{
        user,
        jwt.StandardClaims{
            ExpiresAt: expireAt,
            Issuer:    user.Name,
            IssuedAt:  time.Now().Unix(),
        },
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    tokenStr, err := token.SignedString(mySigningKey)
    if err != nil {
        fmt.Println("generate json web token failed !! error :", err)
    }
    return tokenStr

}

//解析token
func ParsingToken(tokenString string) (*MyCustomClaims, error) {
    token, err := jwt.ParseWithClaims(
        tokenString,
        &MyCustomClaims{},
        func(token *jwt.Token) (interface{}, error) {
            return []byte(KEY), nil
        })
    if claims, ok := token.Claims.(*MyCustomClaims); ok && token.Valid {
        fmt.Printf("%v %v", claims.LpUser, claims.StandardClaims.ExpiresAt)
        fmt.Println("token will be expired at ", time.Unix(claims.StandardClaims.ExpiresAt, 0))
        return claims, nil
    } else {
        fmt.Println("validate tokenString failed !!!", err)
        return nil, err
    }
}


beego validation无效、失效 golang tag标签的一个坑


来看看结构体

这样 自己用table键吧tag标签搞得整整齐齐的

type People struct {
    Key     string `json:"key"         form:"key"         valid:"Required"`         //id值
    Name    string `json:"name"     form:"name"     valid:"Required"`         //名字
    Idcard  string `json:"idcard"     form:"idcard"     valid:"Length(18)"`   //身份证
    Iccard  string `json:"iccard"     form:"iccard"`                       //IC卡号
    Sex     int    `json:"sex"         form:"sex"         valid:"Required;Numeric"` //1男 2女
    Picture string `json:"picture"     form:"picture"     valid:"Base64"`     //照片 base64
}

然后我们反射一下看看结果

package main

import (
    "fmt"
    "reflect"
)

type People struct {
    Key     string `json:"key"         form:"key"         valid:"Required"`         //id值
    Name    string `json:"name"     form:"name"     valid:"Required"`         //名字
    Idcard  string `json:"idcard"     form:"idcard"     valid:"Length(18)"`   //身份证
    Iccard  string `json:"iccard"     form:"iccard"`                       //IC卡号
    Sex     int    `json:"sex"         form:"sex"         valid:"Required;Numeric"` //1男 2女
    Picture string `json:"picture"     form:"picture"     valid:"Base64"`     //照片 base64
}

func main() {

    people := People{
        Key: "ccc",
    }

    t := reflect.TypeOf(people)

    for i := 0; i < t.NumField(); i++ {
        key := t.Field(i)
        valid := key.Tag.Get("valid")
        fmt.Println(valid)
    }

}

果然输出结果是空的

2020-07-23T00:50:54.png

然后我们把结构体中的tag标签用空格分开

2020-07-23T00:52:37.png

再执行 反射成功!

2020-07-23T00:53:09.png


结论:

结构体tag标签中不能使用table键(可以用多个空格键,或者不用空格)

golang github死锁挑战二


https://github.com/GoesToEleven/GolangTraining/blob/master/22_go-routines/10_deadlock-challenges/03_deadlock-challenge/main.go

package main

import (
    "fmt"
)

func main() {

    c := make(chan int)

    go func() {
        for i := 0; i < 10; i++ {
            c <- i
        }
    }()

    fmt.Println(<-c)

}
//为什么只显示零?
//并且该怎么做才能打印所有0-9个数字?

解决方法一

停止携程 用for读取通道

package main

import (
    "fmt"
)

func main() {

    c := make(chan int)

    go func() {
        for i := 0; i < 10; i++ {
            c <- i
        }
        //关闭通道
        close(c)
    }()

    for {
        x, ok := <-c  //如果不关闭通道的话 这里会导致死锁,因为通道中没有值写入 这里一直一直一直会等待导致死锁
        if !ok { //判断通道是否关闭
            return
        }
        fmt.Println(x, ok)
    }

}

解决方法二

停止携程 用使用for-range读取通道

package main

import (
    "fmt"
)

func main() {

    c := make(chan int)

    go func() {
        for i := 0; i < 10; i++ {
            c <- i
        }
        //关闭通道
        close(c)
    }()

    for v := range c {
        fmt.Println(v)
    }
}

兴趣话题

下面代码为什么 会无限输出000000000000000000000000000.......?

package main

import (
    "fmt"
)

func main() {

    c := make(chan int)

    go func() {
        for i := 0; i < 10; i++ {
            c <- i
        }
        //关闭通道
        close(c)
    }()

    for {
        fmt.Println(<-c) //为什么会一直输出00000000000000?
    }
    // for v := range c {
    //     fmt.Println(v)
    // }
}

golang github死锁挑战一


https://github.com/GoesToEleven/GolangTraining/tree/master/22_go-routines/10_deadlock-challenges

package main

import (
    "fmt"
)

func main() {
    c := make(chan int)
    c <- 1
    fmt.Println(<-c)
}
//这会导致死锁。
//您能确定原因吗?
//而您将如何解决?

解决方法一:

通道加缓存

package main

import (
    "fmt"
)

func main() {
    c := make(chan int,1)
    c <- 1
    fmt.Println(<-c)
}

解决方法二:

加协程

package main

import (
    "fmt"
)

func main() {
    c := make(chan int)
    go func() {
        c <- 1
    }()
    fmt.Println(<-c)
}