美文网首页
go-zero微服务《案例一:mysql的CURD操作》

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

作者: voidFan | 来源:发表于2022-07-04 21:57 被阅读0次

    使用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:<passwd>@(127.0.0.1:3306)/<database_name>?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操作》

          本文链接:https://www.haomeiwen.com/subject/cirjbrtx.html