用于记录一些学习 Golang Web 开发用到的东西

# 用户

# 用户注册 - 邮箱验证码与 uuid

# 使用 go.uuid 给用户生成 uuid:

  1. 获取 go.uuid

    1
    go get github.com/satori/go.uuid
  2. 生成 uuid

    1
    2
    3
    4
    5
    6
    7
    8
    package util

    import uuid "github.com/satori/go.uuid"

    func GenerateUUID() string {
    //使用uuid.NewV4().String()生成一个uuid,该uuid共有36位
    return uuid.NewV4().String()
    }

# 使用 email 来发送邮件:

  1. 获取 email

    1
    go get github.com/jordan-wright/email
  2. 配置发送信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    package util

    import (
    "crypto/tls"
    "errors"
    "github.com/jordan-wright/email"
    "net/smtp"
    )

    func SendCode(toUserEmail, code string) error {
    //toUserEmail是接收者邮箱,code是生成的验证码
    e := email.NewEmail()

    //使用From填写发送者的信息
    e.From = "OnlineLearn <发送者邮箱>"
    //To填写接收者邮箱
    e.To = []string{toUserEmail}
    //Subject为项目描述
    e.Subject = "验证码发送测试"
    //发送内容
    e.HTML = []byte("您的验证码是:<b>" + code + "</b>")

    //这里以163邮箱为例:
    //err := e.Send("smtp.163.com:465", smtp.PlainAuth("", "Sender's [email protected]", "SMTP授权码", "smtp.163.com"))

    //如果使用上面这条语句提示EOF,则使用下面的发送语句,跳过tls验证
    err := e.SendWithTLS("smtp.163.com:465", smtp.PlainAuth("", "Sender's [email protected]", "SMTP授权码", "smtp.163.com"),
    &tls.Config{InsecureSkipVerify: true, ServerName: "smtp.163.com"})
    if err != nil {
    err := errors.New("Send Email Code Error!")
    return err
    }

    return nil
    }
  3. 生成验证码并发送,写入 redis 等待验证

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    func SendCode(c *gin.Context) {
    //获取postform传来的email
    email := c.PostForm("email")

    if email == "" {
    c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "邮箱错误!"})
    }

    //生成6位随机验证码
    rand.NewSource(time.Now().Unix())
    number := []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}
    var code string
    for i := 0; i < 6; i++ {
    code += number[rand.Intn(len(number))]
    }

    //写入到redis数据库中,redis如何使用可以查看:2、数据库
    rdb.Set(ctx, email, code, time.Minute*5)
    //使用上面配置好的SendCode函数发送验证码
    err := util.SendCode(email, code)
    if err != nil {
    log.Println("Code Send Error: " + err.Error())
    c.JSON(http.StatusOK, gin.H{"code": -1, "msg": "验证码发送失败!"})
    return
    }

    c.JSON(http.StatusOK, gin.H{"code": 200, "msg": "验证码发送成功!"})
    }

# 用户登录 - token

使用 jwt 生成 token:

  1. 获取 jwt

    1
    go get -u github.com/golang-jwt/jwt/v5
  2. 定义 UserClaims

    1
    2
    3
    4
    5
    type UserClaims struct {
    Identity string `json:"identity"` //唯一标识
    Name string `json:"name"` //用户名
    jwt.StandardClaims //jwt自带的标准Claims
    }
  3. 生成 token

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var myKey = []byte("OnlineLearn-jwt-key")
    // 生成token
    func GenerateToken(identity, name string) (string, error) {
    userClaims := &UserClaims{
    Identity: identity,
    Name: name,
    StandardClaims: jwt.StandardClaims{},
    }

    //使用SigningMethodHS256的加密方式进行加密,返回字节流token
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, userClaims)
    //将字节流转换为字符串
    tokenString, err := token.SignedString(myKey)
    if err != nil {
    return "", err
    }
    //fmt.Println(tokenString)
    return tokenString, nil
    }
  4. 解析 token

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    func AnalyseToken(tokenString string) (*UserClaims, error) {
    userClaims := new(UserClaims)
    //使用jwt提供给的ParseWithClaims函数解析token
    claims, err := jwt.ParseWithClaims(tokenString, userClaims, func(token *jwt.Token) (interface{}, error) {
    return myKey, nil
    })
    if err != nil {
    return nil, err
    }
    if !claims.Valid {
    return nil, fmt.Errorf("analyse Token Error:%v", err)
    }
    return userClaims, nil
    }

# 密码加密

使用 md5 进行加密:

1
2
3
func GetMd5(s string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(s)))
}

# 数据库

# 读取数据库配置信息

使用 viper 读取配置文件中的配置信息:

  1. 获取 viper

    1
    go get github.com/spf13/viper
  2. 配置 config.yml 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #示例:
    Server:
    port: 8080
    Mysql:
    driverName: mysql
    username: ailzr
    password: 123456
    host: 192.168.109.136
    port: 3306
    database: Test
    charset: utf8mb4
    Redis:
    driverName: redis
    username:
    password: 123456
    host: 192.168.109.136
    port: 6379
    database: 0
  3. 使用 viper 载入配置信息文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package conf

    import (
    "fmt"
    "github.com/spf13/viper"
    "os"
    )

    func init() {
    //载入配置信息文件
    workDir, _ := os.Getwd()
    viper.SetConfigName("config")
    viper.SetConfigType("yml")
    viper.AddConfigPath(workDir + "/conf")
    err := viper.ReadInConfig()
    if err != nil {
    panic(err)
    }
    fmt.Println("config load success ...")
    }
    //使用init函数可以直接在main包里匿名导入
  4. 获取配置信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //这里以Mysql为例
    func InitDB() *gorm.DB {
    //获取配置文件参数
    driverName := viper.GetString("Mysql.driverName")
    username := viper.GetString("Mysql.username")
    password := viper.GetString("Mysql.password")
    host := viper.GetString("Mysql.host")
    port := viper.GetString("Mysql.port")
    database := viper.GetString("Mysql.database")
    charset := viper.GetString("Mysql.charset")

    args := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=%s&parseTime=true&loc=Local", username, password, host, port, database, charset)

    //创建数据库连接
    db, err := gorm.Open(driverName, args)
    if err != nil {
    panic(err)
    }

    fmt.Println("database connect success ...")
    return db
    }

# Go-Redis

使用 Go-Redis 操作 Redis 数据库:

获取 Go-Redis:

1
go get github.com/redis/go-redis/v9

配置 Redis:

1
2
3
4
5
6
7
var ctx = context.Background()

var rdb = redis.NewClient(&redis.Options{
Addr: "host:port",
Password: "password",
DB: 0,
})

Set 写入:

1
2
3
4
5
6
7
8
9
10
11
//原型
func (c cmdable) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd

//使用:
ok, err := rdb.Set(ctx, "name", "mmc", time.Second*10).Result()
//写入成功ok会返回OK
if err != nil {
fmt.Println(err)
return
}
fmt.Println(ok)

Get 获取:

1
2
3
4
5
6
7
8
9
10
//原型
func (c cmdable) Get(ctx context.Context, key string) *StringCmd

//使用:
v, err := rdb.Get(ctx, "name").Result()
//获取到的value返回给v
if err != nil {
t.Fatal(err)
}
fmt.Println(v)

# Go-Swagger

  1. 获取 gin-swagger

    1
    2
    3
    4
    go get -u github.com/swaggo/swag/cmd/swag

    #Go 1.17版本之后不支持使用go get安装文件,所以1.17版本之后的Go使用如下指令获取gin-swagger
    go install github.com/swaggo/swag/cmd/swag@latest
  2. 下载 gin-swagger

    1
    2
    go get -u github.com/swaggo/gin-swagger
    go get -u github.com/swaggo/files
  3. 使用 gin 给 gin-swagger 添加路由

    1
    r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
  4. 导入一些配置

    1
    2
    3
    4
    5
    import (
    _ "项目/docs"//导入docs之前需要使用swag init生成docs文件夹
    swaggerfiles "github.com/swaggo/files"
    ginSwagger "github.com/swaggo/gin-swagger"
    )
  5. 配置接口信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //例如

    // Register
    // @Tags 公共方法
    // @Summary 用户注册
    // @Param mail formData string true "mail"
    // @Param name formData string true "name"
    // @Param password formData string true "password"
    // @Param code formData string true "code"
    // @Param phone formData string false "phone"
    // @Success 200 {string} json "{"code":"200","data":""}"
    // @Router /user/register [post]
    func Register(c *gin.Context){}

    //说明:
    // 接口名:Register
    // 接口标签:公共方法
    // 接口描述:用户注册
    // 接口参数:参数名为mail 发送形式为form 字符串类型 必须发送(false为可发可不发) "对该参数的描述"
    // 接口参数:参数名name 同上
    // Param都同上....
    // 成功返还信息:http状态码 {string} json "内容"
    // 路由路径:路径 [请求方式]