go-zero微服务《案例一:mysql的CURD操作》

  • 参考案例:https://www.jianshu.com/p/51c5e98bd6c3

使用goctl自动生成api数据模型的代码

  • goctl安装
#  for Go 1.15 and earlier
go get -u github.com/zeromicro/go-zero/tools/goctl@latest
go install github.com/zeromicro/go-zero/tools/goctl@latest

# for Go 1.16 and later
go install github.com/zeromicro/go-zero/tools/goctl@latest
  • 定义xxx.api文档

// 1. 用户注册/open/register; 入参(mobile:手机号,passwd:密码,code:图片验证码)
// 2. 用户登录/open/authorization;  入参(mobile:手机号,passwd:密码,code:图片验证码)
// 3. 图片验证码请求/open/verify; ticket:图片验证码的id; data:base64格式的图片
type (
    UserOptReq struct {
        mobile string `json:"mobile"`
        passwd string `json:"passwd"`
        code   string `json:"code"`
    }

    UserOptResp struct {
        id    uint   `json:"id"`
        token string `json:"token"`
    }
    //图片验证码支持
    VerifyReq struct {
        ticket string `json:"ticket"`
    }
    //图片验证码支持
    VerifyResp struct {
        data string `json:"data"`
    }
)

// 一个文件里面只能有一个 service
service open-api {
    @doc(
        summary: 公开的api函数
        desc: >
        register: 用户注册,
        authorization: 用户登录,
        verify: 图片验证码接口
    )
    @server(
        handler: registerHandler
        folder: open
    )
    post /open/register(UserOptReq) returns(UserOptResp)
    
    
    @server(
        handler: authorizationHandler
        folder: open
    )
    post /open/authorization(UserOptReq) returns(UserOptResp)

    @server(
        handler: verifyHandler
        folder: open
    )
    post /open/verify(VerifyReq) returns(VerifyResp)
    
}
  • 生成代码
goctl api go -api xxx.api -dir .
# 使用goctl生成api代码,生成go语言代码,api的定义模版本是xxx.api, -dir指定生成的代码路径

集成Gorm操作mysql

  • 修改配置文件 etc/xxx-api.yaml
Name: open-api
Host: 0.0.0.0
Port: 8888
DataSourceName: root:@(127.0.0.1:3306)/?charset=utf8
  • 在internal/config/config.go中添加DataSourceName
type Config struct {
    rest.RestConf
    DataSourceName string
}
  • 修改svc/servicecontext.go
package svc

import (
    "hello/internal/config"
    "hello/internal/models"

    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    "gorm.io/gorm/schema"
)

type ServiceContext struct {
    Config  config.Config
    DbEngin *gorm.DB
}

func NewServiceContext(c config.Config) *ServiceContext {
    //启动Gorm支持
    db, err := gorm.Open(mysql.Open(c.DataSourceName), &gorm.Config{
        NamingStrategy: schema.NamingStrategy{
            TablePrefix:   "tech_", // 表名前缀,`User` 的表名应该是 `t_users`
            SingularTable: true,    // 使用单数表名,启用该选项,此时,`User` 的表名应该是 `t_user`
        },
    })
    //如果出错就GameOver了
    if err != nil {
        panic(err)
    }
    //自动同步更新表结构,不要建表了O(∩_∩)O哈哈~
    db.AutoMigrate(&models.User{})

    return &ServiceContext{Config: c, DbEngin: db}
}

  • 新建数据库的 models\models.go
//models\models.go文件
package models

import (
    "errors"
    "hello/internal/utils"

    "gorm.io/gorm"
)

type User struct {
    gorm.Model
    Mobile string `gorm:"index:mobile;type:varchar(13)"`
    Passwd string `gorm:"type:varchar(64)"`
}
//在创建前检验验证一下密码的有效性
func (u *User) BeforeCreate(db *gorm.DB) error {
    if len(u.Passwd) < 6 {
        return errors.New("密码太简单了")
    }
    //对密码进行加密存储
    u.Passwd = utils.Password(u.Passwd)
    return nil
}
  • 新建utils utils.Password工具包
package utils

import (
    "fmt"

    "golang.org/x/crypto/bcrypt"
)

//密码加密
func Password(plainpwd string) string {
    //谷歌的加密包
    hash, err := bcrypt.GenerateFromPassword([]byte(plainpwd), bcrypt.DefaultCost) //加密处理
    if err != nil {
        fmt.Println(err)
    }
    encodePWD := string(hash) // 保存在数据库的密码,虽然每次生成都不同,只需保存一份即可
    return encodePWD
}
//密码校验
func CheckPassword(plainpwd, cryptedpwd string) bool {
    err := bcrypt.CompareHashAndPassword([]byte(cryptedpwd), []byte(plainpwd)) //验证(对比)
    return err == nil
}

  • 修改实现业务逻辑 logic\xxx\registerlogic.go
package logic

import (
    "context"

    "hello/internal/models"
    "hello/internal/svc"
    "hello/internal/types"

    "github.com/tal-tech/go-zero/core/logx"
)

type RegisterLogic struct {
    ctx context.Context
    logx.Logger
    svcCtx *svc.ServiceContext
}

func NewRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) RegisterLogic {
    return RegisterLogic{
        ctx:    ctx,
        Logger: logx.WithContext(ctx),
        svcCtx: svcCtx,
    }
}

func (l *RegisterLogic) Register(req types.UserOptReq) (*types.UserOptResp, error) {
    user := models.User{
        Mobile: req.Mobile,
        Passwd: req.Passwd,
    }
    result := l.svcCtx.DbEngin.Create(&user)
    return &types.UserOptResp{
        Id: user.ID,
    }, result.Error
}

你可能感兴趣的:(go-zero微服务《案例一:mysql的CURD操作》)