这是我参与「第三届青训营 -后端场」笔记创作活动的的第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 加密
-
声明一串用于加密解密的秘钥
//定义一个全局变量 //加密秘钥 var mySigningKey = []byte("douyinQ") -
生成原生未加密的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, //过期时间: 一天 }) -
使用秘钥加密并返回token
//使用秘钥加密token tokenString, err := token.SignedString(mySigningKey) if err != nil { return "", err } return tokenString, nil
9.2 解密
-
获取原生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 } -
从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
}
\