1 生成模型
(1) 由sql脚本生成go模型
CREATE TABLE `user` (`id` bigint unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) NOT NULL DEFAULT '' COMMENT '用户姓名',`gender` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '用户性别',`mobile` varchar(255) NOT NULL DEFAULT '' COMMENT '用户电话',`password` varchar(255) NOT NULL DEFAULT '' COMMENT '用户密码',`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`),UNIQUE KEY `idx_mobile_unique` (`mobile`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
goctl model mysql ddl -src ./model/user.sql -dir ./model -c
(2) 由数据库生成go模型
goctl model mysql datasource —url “root:password@tcp(127.0.0.1:3306)/database” -dir ./model
2 api生成go文件
(1) 编写api文件
type (// 用户登录LoginRequest {Mobile string `json:"mobile"`Password string `json:"password"`}LoginResponse {AccessToken string `json:"accessToken"`AccessExpire int64 `json:"accessExpire"`}// 用户登录// 用户注册RegisterRequest {Name string `json:"name"`Gender int64 `json:"gender"`Mobile string `json:"mobile"`Password string `json:"password"`}RegisterResponse {Id int64 `json:"id"`Name string `json:"name"`Gender int64 `json:"gender"`Mobile string `json:"mobile"`}// 用户注册// 用户信息UserInfoResponse {Id int64 `json:"id"`Name string `json:"name"`Gender int64 `json:"gender"`Mobile string `json:"mobile"`}// 用户信息)service User {@handler Loginpost /api/user/login(LoginRequest) returns (LoginResponse)@handler Registerpost /api/user/register(RegisterRequest) returns (RegisterResponse)}@server(jwt: Auth)service User {@handler UserInfopost /api/user/userinfo returns (UserInfoResponse)}
(2) 根据api生成go代码
goctl api go -api ./api/user.api -dir ./api
3 proto生成go文件
(1) 编写proto文件
syntax = "proto3";package userclient;option go_package = "./user";// 用户登录message LoginRequest {string Mobile = 1;string Password = 2;}message LoginResponse {int64 Id = 1;string Name = 2;int64 Gender = 3;string Mobile = 4;}// 用户登录// 用户注册message RegisterRequest {string Name = 1;int64 Gender = 2;string Mobile = 3;string Password = 4;}message RegisterResponse {int64 Id = 1;string Name = 2;int64 Gender = 3;string Mobile = 4;}// 用户注册// 用户信息message UserInfoRequest {int64 Id = 1;}message UserInfoResponse {int64 Id = 1;string Name = 2;int64 Gender = 3;string Mobile = 4;}// 用户信息service User {rpc Login(LoginRequest) returns(LoginResponse);rpc Register(RegisterRequest) returns(RegisterResponse);rpc UserInfo(UserInfoRequest) returns(UserInfoResponse);}
(2) 根据proto生成go代码
goctl rpc protoc user.proto —go_out=./ —go-grpc_out=./ —zrpc_out=./
4 编写rpc服务
(1) 修改配置文件
rpc/etc/user.yaml
Name: user.rpcListenOn: 0.0.0.0:9000Etcd:Hosts:- etcd:2379Key: user.rpcMysql:DataSource: root:123456@tcp(mysql:3306)/mall?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghaiCacheRedis:- Host: redis:6379Type: node
(2) 添加 model 依赖
vim rpc/internal/config/config.go
package configimport ("github.com/zeromicro/go-zero/core/stores/cache""github.com/zeromicro/go-zero/zrpc")type Config struct {zrpc.RpcServerConfMysql struct {DataSource string}CacheRedis cache.CacheConf}
vim rpc/internal/svc/servicecontext.go
package svcimport ("mall/service/user/model""mall/service/user/rpc/internal/config""github.com/zeromicro/go-zero/core/stores/sqlx")type ServiceContext struct {Config config.ConfigUserModel model.UserModel}func NewServiceContext(c config.Config) *ServiceContext {conn := sqlx.NewMysql(c.Mysql.DataSource)return &ServiceContext{Config: c,UserModel: model.NewUserModel(conn, c.CacheRedis),}}
(3) 添加业务逻辑
1) 添加工具库
vim common/cryptx/crypt.go
package cryptximport ("fmt""golang.org/x/crypto/scrypt")func PasswordEncrypt(salt, password string) string {dk, _ := scrypt.Key([]byte(password), []byte(salt), 32768, 8, 1, 32)return fmt.Sprintf("%x", string(dk))}
2) 添加配置信息
vim rpc/etc/user.yaml
Name: user.rpcListenOn: 0.0.0.0:9000...Salt: HWVOFkGgPTryzICwd7qnJaZR9KQ2i8xe
vim rpc/internal/config/config.go
package configimport ("github.com/zeromicro/go-zero/core/stores/cache""github.com/zeromicro/go-zero/zrpc")type Config struct {...Salt string}
3) 添加逻辑
vim rpc/internal/logic/registerlogic.go
package logicimport ("context""mall/common/cryptx""mall/service/user/model""mall/service/user/rpc/internal/svc""mall/service/user/rpc/user""github.com/zeromicro/go-zero/core/logx""google.golang.org/grpc/status")type RegisterLogic struct {ctx context.ContextsvcCtx *svc.ServiceContextlogx.Logger}func NewRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RegisterLogic {return &RegisterLogic{ctx: ctx,svcCtx: svcCtx,Logger: logx.WithContext(ctx),}}func (l *RegisterLogic) Register(in *user.RegisterRequest) (*user.RegisterResponse, error) {// 判断手机号是否已经注册_, err := l.svcCtx.UserModel.FindOneByMobile(in.Mobile)if err == nil {return nil, status.Error(100, "该用户已存在")}if err == model.ErrNotFound {newUser := model.User{Name: in.Name,Gender: in.Gender,Mobile: in.Mobile,Password: cryptx.PasswordEncrypt(l.svcCtx.Config.Salt, in.Password),}res, err := l.svcCtx.UserModel.Insert(&newUser)if err != nil {return nil, status.Error(500, err.Error())}newUser.Id, err = res.LastInsertId()if err != nil {return nil, status.Error(500, err.Error())}return &user.RegisterResponse{Id: newUser.Id,Name: newUser.Name,Gender: newUser.Gender,Mobile: newUser.Mobile,}, nil}return nil, status.Error(500, err.Error())}
6 编写api服务
(1) 修改配置文件
vim api/etc/user.yaml
Name: UserHost: 0.0.0.0Port: 8000...Auth:AccessSecret: uOvKLmVfztaXGpNYd4Z0I1SiT7MweJhlAccessExpire: 86400UserRpc:Etcd:Hosts:- etcd:2379Key: user.rpc
(2) 添加 rpc依赖
vim api/internal/config/config.go
package configimport ("github.com/zeromicro/go-zero/rest""github.com/zeromicro/go-zero/zrpc")type Config struct {rest.RestConfAuth struct {AccessSecret stringAccessExpire int64}UserRpc zrpc.RpcClientConf}
vim api/internal/svc/servicecontext.go
package svcimport ("mall/service/user/api/internal/config""mall/service/user/rpc/userclient""github.com/zeromicro/go-zero/zrpc")type ServiceContext struct {Config config.ConfigUserRpc userclient.User}func NewServiceContext(c config.Config) *ServiceContext {return &ServiceContext{Config: c,UserRpc: userclient.NewUser(zrpc.MustNewClient(c.UserRpc)),}}
(3) 添加业务逻辑
vim api/internal/logic/registerlogic.go
package logicimport ("context""mall/service/user/api/internal/svc""mall/service/user/api/internal/types""mall/service/user/rpc/userclient""github.com/zeromicro/go-zero/core/logx")type RegisterLogic struct {logx.Loggerctx context.ContextsvcCtx *svc.ServiceContext}func NewRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) RegisterLogic {return RegisterLogic{Logger: logx.WithContext(ctx),ctx: ctx,svcCtx: svcCtx,}}func (l *RegisterLogic) Register(req types.RegisterRequest) (resp *types.RegisterResponse, err error) {res, err := l.svcCtx.UserRpc.Register(l.ctx, &userclient.RegisterRequest{Name: req.Name,Gender: req.Gender,Mobile: req.Mobile,Password: req.Password,})if err != nil {return nil, err}return &types.RegisterResponse{Id: res.Id,Name: res.Name,Gender: res.Gender,Mobile: res.Mobile,}, nil}
7 启动服务
(1) 启动rpc服务
$ cd mall/service/user/rpc $ go run user.go -f etc/user.yaml Starting rpc server at 127.0.0.1:9000…
(2) 启动api服务
$ cd mall/service/user/api $ go run user.go -f etc/user.yaml Starting server at 0.0.0.0:8000…
