标签 go 下的文章

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 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)
}

golang websocket并发


WsConn *websocket.Conn 并发不安全 不能同时写
panic: concurrent write to websocket connection

package cws
 
import (
    "errors"
    "github.com/gorilla/websocket"
    "sync"
)
 
//封装websocket并发读写操作
 
type Connection struct {
    WsConn    *websocket.Conn
    InChan    chan []byte
    OutChan   chan models.BayDataS
    CloseChan chan byte
    Mutex     sync.Mutex
    IsClosed  bool
}
 
func InitConnection(wsConn *websocket.Conn) (conn *Connection, err error) {
    conn = &Connection{
        WsConn:    wsConn,
        InChan:    make(chan []byte, 1000),
        OutChan:   make(chan []byte, 1000),
        CloseChan: make(chan byte, 1),
    }
    //读协程
    go conn.ReadLoop()
    //写协程
    go conn.WriteLoop()
    return
}
 
func (conn *Connection) ReadMess() (data []byte, err error) {
    select {
    case data = <-conn.InChan:
    case <-conn.CloseChan:
        err = errors.New("connection is closed")
    }
    return
}
 
func (conn *Connection) WriteMes(data []byte) (err error) {
    select {
    case conn.OutChan <- data:
    case <-conn.CloseChan:
        err = errors.New("connection is closed")
    }
    return
}
 
func (conn *Connection) Close() {
    conn.WsConn.Close() //本身线程安全,可重入
    //加锁,只能执行一次
    conn.Mutex.Lock()
    if !conn.IsClosed {
        close(conn.CloseChan)
        conn.IsClosed = true
    }
}
 
//具体实现读消息
func (conn *Connection) ReadLoop() {
    var (
        data []byte
        err  error
    )
    for {
        if _, data, err = conn.WsConn.ReadMessage(); err != nil {
            goto ERR
        }
        select {
        case conn.InChan <- data:
        case <-conn.CloseChan:
            goto ERR
        }
    }
ERR:
    conn.Close()
}
 
//具体实现写消息
func (conn *Connection) WriteLoop() {
    var (
        data models.BayDataS
        err  error
    )
    for {
        select {
        case data = <-conn.OutChan:
        case <-conn.CloseChan:
            goto ERR
        }
        if err = conn.WsConn.WriteMessage(websocket.TextMessage, data); err != nil {
            goto ERR
        }
    }
ERR:
    conn.Close()
}

golang base64保存文件


golang:


/**
 * @description: base64 文件保存
 * @param 路径,文件名,内容
 * @return:
 */
func Base64ToFile(path, fileName, base64Str string) (err error) {
    err = os.MkdirAll(path, 0777) //创建目录
    if err != nil {
        return err
    }

    ddd, err := base64.StdEncoding.DecodeString(base64Str)
    if err != nil {
        return err
    }

    err = ioutil.WriteFile(path+fileName, ddd, 0666) //buffer输出文件中(不做处理,直接写到文件)
    if err != nil {
        return err
    }
    return nil
}