使用goctl自動(dòng)生成api數(shù)據(jù)模型的代碼
# 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
// 1. 用戶注冊/open/register; 入?yún)ⅲ╩obile:手機(jī)號,passwd:密碼,code:圖片驗(yàn)證碼)
// 2. 用戶登錄/open/authorization; 入?yún)ⅲ╩obile:手機(jī)號,passwd:密碼,code:圖片驗(yàn)證碼)
// 3. 圖片驗(yàn)證碼請求/open/verify; ticket:圖片驗(yàn)證碼的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"`
}
//圖片驗(yàn)證碼支持
VerifyReq struct {
ticket string `json:"ticket"`
}
//圖片驗(yàn)證碼支持
VerifyResp struct {
data string `json:"data"`
}
)
// 一個(gè)文件里面只能有一個(gè) service
service open-api {
@doc(
summary: 公開的api函數(shù)
desc: >
register: 用戶注冊,
authorization: 用戶登錄,
verify: 圖片驗(yàn)證碼接口
)
@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
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
}
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 {
//啟動(dòng)Gorm支持
db, err := gorm.Open(mysql.Open(c.DataSourceName), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: "tech_", // 表名前綴,`User` 的表名應(yīng)該是 `t_users`
SingularTable: true, // 使用單數(shù)表名,啟用該選項(xiàng),此時(shí),`User` 的表名應(yīng)該是 `t_user`
},
})
//如果出錯(cuò)就GameOver了
if err != nil {
panic(err)
}
//自動(dòng)同步更新表結(jié)構(gòu),不要建表了O(∩_∩)O哈哈~
db.AutoMigrate(&models.User{})
return &ServiceContext{Config: c, DbEngin: db}
}
- 新建數(shù)據(jù)庫的 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)"`
}
//在創(chuàng)建前檢驗(yàn)驗(yàn)證一下密碼的有效性
func (u *User) BeforeCreate(db *gorm.DB) error {
if len(u.Passwd) < 6 {
return errors.New("密碼太簡單了")
}
//對密碼進(jìn)行加密存儲
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) // 保存在數(shù)據(jù)庫的密碼,雖然每次生成都不同,只需保存一份即可
return encodePWD
}
//密碼校驗(yàn)
func CheckPassword(plainpwd, cryptedpwd string) bool {
err := bcrypt.CompareHashAndPassword([]byte(cryptedpwd), []byte(plainpwd)) //驗(yàn)證(對比)
return err == nil
}
- 修改實(shí)現(xiàn)業(yè)務(wù)邏輯 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
}