Go语言基础笔记(六)| 青训营笔记

145 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第6篇笔记。

7、GORM框架

使用:

 go get -u gorm.io/gorm
 go get -u gorm.io/driver/mysql

7.1 连接数据库

连接不同的数据库都需要导入对应数据的驱动程序,GORM已经贴心的为我们包装了一些驱动程序,只需要按如下方式导入需要的数据库驱动即可:

 import "gorm.io/driver/mysql"

连接MySQL

 package main
 ​
 import (
     "fmt"
     "gorm.io/driver/mysql"
     "gorm.io/gorm"
 )
 ​
 func main() {
     dsn := "root:root@(localhost:3306)/go_db1?charset=utf8mb4&parseTime=True&loc=Local"
     db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
 }

高级配置

 db, err := gorm.Open(mysql.New(mysql.Config{
     DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source name
     DefaultStringSize: 256, // string 类型字段的默认长度
     DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
     DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
     DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
     SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
 }), &gorm.Config{})

连接池

GORM 使用 database/sql 维护连接池

 pool, err := db.DB()
 if err != nil {
     return err
 }
 // 连接的最大可复用(存活)时间
     pool.SetConnMaxIdleTime(60000000000)
     // 设置空闲连接池中连接的最大数量
     pool.SetMaxOpenConns(5)
     // 设置打开数据库连接的最大数量。
     pool.SetMaxIdleConns(10)
     // 最大的建立连接时间
     pool.SetConnMaxLifetime(60000000000)

7.2 Gorm操作数据库

8、GO-Redis框架

go get github.com/garyburd/redigo/redis

8.1 获取连接

 package main
 ​
 import (
     "fmt"
     "github.com/garyburd/redigo/redis"
 )
 ​
 func main() {
     c, err := redis.Dial("tcp",
         "124.70.69.180:6379",
         redis.DialPassword("123456"))
     if err != nil {
         fmt.Println("conn redis failed,", err)
         return
     }
 ​
     fmt.Println("redis conn success")
     defer c.Close()
 }

8.2 String类型Set、Get操作

 package main
 ​
 import (
     "fmt"
     "github.com/garyburd/redigo/redis"
 )
 ​
 func main() {
     //获取conn
     c, err := redis.Dial("tcp",
         "124.70.69.180:6379",
         redis.DialPassword("123456"))
     if err != nil {
         fmt.Println("conn redis failed,", err)
         return
     }
 ​
     fmt.Println("redis conn success")
     defer c.Close()
 ​
     //Set操作
     _,err = c.Do("Set","k1","v1")
     if err != nil {
         fmt.Println(err)
         return
     }
     //Get操作
     r, err := redis.String(c.Do("Get", "k1"))
     if err != nil {
         fmt.Println("get k1 failed,", err)
         return
     }
 ​
     fmt.Println(r)
 }

8.3 批量操作

 package main
 ​
 import (
     "fmt"
     "github.com/garyburd/redigo/redis"
 )
 ​
 func main() {
     c, err := redis.Dial("tcp",
         "124.70.69.180:6379",
         redis.DialPassword("123456"))
     if err != nil {
         fmt.Println("conn redis failed,", err)
         return
     }
 ​
     fmt.Println("redis conn success")
     defer c.Close()
     
     //批量Set、Get操作
     _,err = c.Do("MSet","k2",100,"k3",200)
     if err!=nil{
         fmt.Println(err)
         return
     }
     results,err := redis.Strings(c.Do("MGet","k1","k2","k3"))
     if err!=nil{
         fmt.Println("get failed")
         return
     }
     for _,r := range results{
         fmt.Println(r)
     }
 ​
 }
 ​

8.4 设置过期时间

 package main
 ​
 import (
     "fmt"
     "github.com/garyburd/redigo/redis"
 )
 ​
 func main() {
     c, err := redis.Dial("tcp",
         "124.70.69.180:6379",
         redis.DialPassword("123456"))
     if err != nil {
         fmt.Println("conn redis failed,", err)
         return
     }
 ​
     fmt.Println("redis conn success")
     defer c.Close()
 ​
     //设置过期时间
     _, err = c.Do("expire", "k2", 10)
     if err != nil {
         fmt.Println(err)
         return
     }
 ​
 }
 ​

9、go-jwt

go get -u github.com/dgrijalva/jwt-go

9.1 加密

  1. 声明一串用于加密解密的秘钥

     //定义一个全局变量
     //加密秘钥
     var mySigningKey = []byte("douyinQ")
    
  2. 生成原生未加密的token

     然后使用jwt.NewWithClaimsnew一个token,这个函数有两个参数,返回值就是token
     第一个是加密方法,我这里使用的是hs256加密
     第二个是加密的一些参数,可以使用自带的jwt.MapClaims,也可以自定义一个结构体,如果是自定义结构体需要实现jwt.StandardClaims结构体,里面可以定义过期时间等等
     type StandardClaims struct {
         Audience  string `json:"aud,omitempty"`
         ExpiresAt int64  `json:"exp,omitempty"`
         Id        string `json:"jti,omitempty"`
         IssuedAt  int64  `json:"iat,omitempty"`
         Issuer    string `json:"iss,omitempty"`
         NotBefore int64  `json:"nbf,omitempty"`
         Subject   string `json:"sub,omitempty"`
     }
     而jwt.MapClaims本质上是一个map集合
     type MapClaims map[string]interface{}
     这里只需要将id传入,所以使用MapClaims
     ​
     //加密方法,使用的是hs256加密
         //加密用户id
         token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
             "id":  id,
             "exp": time.Now().Unix() + 24*60*60, //过期时间: 一天
         })
    
  3. 使用秘钥加密并返回token

     //使用秘钥加密token
         tokenString, err := token.SignedString(mySigningKey)
         if err != nil {
             return "", err
         }
         return tokenString, nil
    

9.2 解密

  1. 获取原生token

     解密使用jwt.Parse方法,如果上面使用了自定义结构体的话就使用jwt.ParseWithClaims方法
     jwt.Parse有两个参数
     第一个就是加密后的token字符串
     第二个是一个自带的回调函数,将秘钥和错误return出来即可
     jwt.ParseWithClaims有三个参数
     第一个就是加密后的token字符串
     第二个是加密使用的模板,例如上面示例将qqq传入即可
     第三个是一个自带的回调函数,将秘钥和错误return出来即可
     ​
     //获取原始token
     tokenOriginal, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
         return mySigningKey, nil
     })
     //可以判断token是否过期
     if err != nil {
         return 0, err
     }
    
  2. 从token获取参数

     //interface{}中数值类型默认为float64
     id := tokenOriginal.Claims.(jwt.MapClaims)["id"].(float64)
     //返回int类型的id
     return int(id), nil
    

9.3 jwt_util.go

 package jwt
 ​
 import (
     "github.com/dgrijalva/jwt-go"
     "time"
 )
 ​
 //加密秘钥
 var mySigningKey = []byte("douyinQ")
 ​
 func CreateJWT(id int) (string, error) {
 ​
     //加密方法,使用的是hs256加密
     //加密用户id
     token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
         "id":  id,
         "exp": time.Now().Unix() + 24*60*60, //过期时间: 一天
     })
     //使用秘钥加密token
     tokenString, err := token.SignedString(mySigningKey)
     if err != nil {
         return "", err
     }
     return tokenString, nil
 }
 ​
 func ParseJWT(token string) (int, error) {
     //获取原始token
     tokenOriginal, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
         return mySigningKey, nil
     })
     //可以判断token是否过期
     if err != nil {
         return 0, err
     }
     //interface{}中数值类型默认为float64
     id := tokenOriginal.Claims.(jwt.MapClaims)["id"].(float64)
     //返回int类型的id
     return int(id), nil
 }

\