最近使用 gin 的总结

最近有新项目是利用gin开发的,过程中遇到一些问题,总结一下,作为笔记,也希望能帮助到你。

跨域问题

中间件:

func Cors() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 这里可以用*,也可以用你指定的域名
        c.Header("Access-Control-Allow-Origin", "*")
        // 允许头部参数
        c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token")
        // 允许的方法
        c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
        c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
        c.Header("Access-Control-Allow-Credentials", "true")

        method := c.Request.Method
        //放行OPTIONS方法
        if method == "OPTIONS" {
            c.AbortWithStatus(http.StatusOK)
        }
        // 处理请求
        c.Next()
    }
}

然后在路由中加入:

// g : *gin.Engine
g.Use(Cors())

当然也可以在Nginx层配置,可自行查阅,我就不展开了。

使用多个中间件

// g : *gin.Engine
g.Use(Cors())
g.Use(Session())

中间件终止请求

func Auth() gin.HandlerFunc {
    return func(c *gin.Context) {
        uid := c.MustGet("uid").(int)
        if uid == 0 {
            c.Abort()
            controller.SendResponse(c, 401, "未登录", nil)
            // return可忽略
            return
        } else {
            c.Next()
        }
    }
}

session使用

package util

import (
    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/redis"
    redisGo "github.com/gomodule/redigo/redis"
    "github.com/spf13/viper"
)

// 启动session
func SessionStart(g *gin.Engine, RedisClient *redisGo.Pool, key ...[]byte)  {
    store, _ := redis.NewStoreWithPool(RedisClient, []byte(viper.GetString("name")))
    redis.SetKeyPrefix(store, "session_")
    g.Use(sessions.Sessions(viper.GetString("name"), store))
}

// 使用session
session  := sessions.Default(c)
session.Set("uid", uid)
uid  := session.Get("uid")

上传oss

import (
    "os"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
    "github.com/spf13/viper"
)
func upload(localPath string, iType int, Name string) (path string) {
    client, err := oss.New(viper.GetString("oss.end_point"), viper.GetString("oss.access_key_id"), viper.GetString("oss.access_key_secret"))
    if err != nil {
        return 
    }

    // 获取存储空间。
    bucket, err := client.Bucket(viper.GetString("oss.bucket"))
    if err != nil {
        return 
    }

    // 上传本地文件。
    ossPath := fmt.Sprintf("%s/%s", "qiling", Name)
    err = bucket.PutObjectFromFile(ossPath, localPath)
    if err != nil {
        return
    }

    path = fmt.Sprintf("%s/%s", viper.GetString("oss.hosts"), ossPath)
    os.Remove(localPath)
    return
}

几个实用的方法

package util

import (
    "fmt"
    "bytes"
    "strings"
    "time"    
    "unicode/utf8"
    "strconv"
    "crypto/md5"
    "net/http"
    "net/url"
    "io/ioutil"
)


// 获取本周一时间戳
func GetFirstDateOfWeekTS() (ts int64) {
    now := time.Now()

    offset := int(time.Monday - now.Weekday())
    if offset > 0 {
        offset = -6
    }

    ts = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset).Unix()
    return
}

// 获取周几时间戳
func GetWeekTS(day int64) (ts int64) {
    thisWeekMonday := GetFirstDateOfWeekTS()
    ts = thisWeekMonday + (day)*86400
    return
}

// 字符串长度
func StrLen(str string) int {
    return utf8.RuneCountInString(str)
}

// 截取字符串
func StrSub(str string, sub ...int) string {
    start := sub[0]
    length := 0
    if len(sub) > 1 {
        length = sub[1]
    }

    if length < 1 {
        return string(([]rune(str))[start:])
    }
    return string(([]rune(str))[start:length])
}

// 合并字符串
func StrCombine(str ...string) string {
    var bt bytes.Buffer
    for _, arg := range str {
        bt.WriteString(arg)
    }
    //获得拼接后的字符串
    return bt.String()
}

func UnicodeIndex(str,substr string) int {
    // 子串在字符串的字节位置
    result := strings.Index(str,substr)  
    if result >= 0 {
      // 获得子串之前的字符串并转换成[]byte
      prefix := []byte(str)[0:result]  
      // 将子串之前的字符串转换成[]rune
      rs := []rune(string(prefix))  
      // 获得子串之前的字符串的长度,便是子串在字符串的字符位置
      result = len(rs)
    }

    return result
}

func ToUnicode(str string) string {
    textQuoted := strconv.QuoteToASCII(str)
    return textQuoted[1 : len(textQuoted)-1]
}

func UnicodeTo(str string) string {
    sUnicodev := strings.Split(str, "\\u")
    var context string
    for _, v := range sUnicodev {
        if len(v) < 1 {
            continue
        }
        temp, err := strconv.ParseInt(v, 16, 32)
        if err != nil {
            panic(err)
        }
        context += fmt.Sprintf("%c", temp)
    }
    return context
}

// 获取当天0点时间抽
func TodayTS() int64 {
    now := time.Now()
    return GetZeroTime(now).Unix()
}

func TodayDate()  string {
    return time.Now().Format("2006/01/02")
}

//获取传入的时间所在月份的第一天,即某月第一天的0点。如传入time.Now(), 返回当前月份的第一天0点时间。
func GetFirstDateOfMonth(d time.Time) time.Time {
    d = d.AddDate(0, 0, -d.Day() + 1)
    return GetZeroTime(d)
}
//获取传入的时间所在月份的最后一天,即某月最后一天的0点。如传入time.Now(), 返回当前月份的最后一天0点时间。
func GetLastDateOfMonth(d time.Time) time.Time {
    return GetFirstDateOfMonth(d).AddDate(0, 1, -1)
}

//获取某一天的0点时间
func GetZeroTime(d time.Time) time.Time {
    return time.Date(d.Year(), d.Month(), d.Day(), 0, 0, 0, 0, d.Location())
}

func Md5(str string) string {
    return fmt.Sprintf("%x", md5.Sum([]byte(str)));
}

func HttpGet(iUrl string, params map[string]string) ([]byte, error) {
    query := ""
    for k, v := range params {
        query = fmt.Sprintf("%s%s=%s&", query, k, url.QueryEscape(v))
    }

    client := http.Client{Timeout: 5 * time.Second} //创建客户端
    resp, err := client.Get(fmt.Sprintf("%s?%s", iUrl, query))
    fmt.Println(iUrl,query)

    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    res, err := ioutil.ReadAll(resp.Body)
    if err!=nil{
        fmt.Println(err)
        return nil,err
    }

    return res, nil
}

大概就这些了,后面有可以分享的再补充。

go
本作品采用《CC 协议》,转载必须注明作者和本文链接
分享开发知识,欢迎交流。公众号:开源到
本帖由系统于 3年前 自动加精
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!