go-zero实战demo(一)
作者:互联网
前言
听说下一个项目 可能要用微服务开发,趁着项目的空档期,对于go微服务的框架进行了学习。目前go的微服务框架个人认为处于百家齐放的时代,可能这也是go的生态的一个特点吧,也曾简单用过go-miecro,gin+micro+gorm+mysql+redis 常见方案使用起来还是蛮顺手的,可惜该框架成了个人仓库,生成的依赖会出现引用错误,其他的都蛮ok的。对于go-zero的选择,其实参考此篇文章:https://zhuanlan.zhihu.com/p/488233067 , 再加团队沟通协商及个人私心(认为其可以成为趋势及给自己加分)。 所以选择的go 微服务框架为go-zero。
版本浅介
go:1.17.6
protoc:3.20.1
goctl:1.3.8
mysql:8.0.29
redis:7.0.0
consul:1.12
demo 介绍
实现简单的用户表 增查
使用consul 替换etcd
相关接口
/api/user/login 登录
�/api/user/register 注册
�/api/user/listuser 查询所有用户
�/api/user/userinfo 查询 某个用户详情
源码:https://github.com/zisefeizhu/go-zero-demo
参考:
go-zero作者
https://www.cnblogs.com/kevinwan/category/2002486.html
go-zero 入门级demo
demo 注意点
常用命令
touch user.api
goctl api go -api ./user.api -dir .
goctl model mysql ddl -src user.sql -dir . -c
touch user.proto
goctl rpc protoc ./rpc/user.proto --go_out=./rpc/types --go-grpc_out=./rpc/types --zrpc_out=./rpc
1、consul 替换etcd
参考文章:https://github.com/zeromicro/zero-contrib/tree/main/zrpc/registry/consul
微服务
rpc/etcd/user.yaml
# consul 替换etcd
Consul:
Host: 127.0.0.1:8500 # consul endpoint
Key: user.rpc # 注册到consul的服务名字
Meta:
Protocol: grpc
Tag:
- tag
- rpc
rpc/internal/config/config.go
type Config struct {
zrpc.RpcServerConf
Mysql struct {
DataSource string
}
// consul
Consul consul.Conf
CacheRedis cache.CacheConf
Salt string
}
rpc/user.go
import (
"github.com/zeromicro/zero-contrib/zrpc/registry/consul"
func main(){
......
err := consul.RegisterService(c.ListenOn, c.Consul)
if err != nil {
os.Exit(1)
}
defer s.Stop()
api
api/etcd/user.yaml
UserRpc:
Target: consul://127.0.0.1:8500/user.rpc?wait=14s
NonBlock: true
api/internalconfig/config.go
type Config struct {
rest.RestConf
Auth struct {
AccessSecret string
AccessExpire int64
}
UserRpc zrpc.RpcClientConf
}
api/user.go
import (
_ "github.com/zeromicro/zero-contrib/zrpc/registry/consul"
)
2、api层的user.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"`
}
// 列出所有用户
ListUserResponse {
Id int64 `json:"id"`
Name string `json:"name"`
Gender int64 `json:"gender"`
Mobile string `json:"mobile"`
}
// 用户信息
)
service User {
@handler Login
post /api/user/login(LoginRequest) returns (LoginResponse)
@handler Register
post /api/user/register(RegisterRequest) returns (RegisterResponse)
@handler ListUser
post /api/user/listuser returns (ListUserResponse)
}
@server(
jwt: Auth
)
service User {
@handler UserInfo
post /api/user/userinfo returns (UserInfoResponse)
}
3、model层
go-zero不会根据sql自动创建表结构,但是可以根据表结构创建dao层
通常只会生成:Insert / FindOne / FindOneByxxx/Update/Delete 方法,其他方法需要自己填充
例:
rpc/model/usermpdel_gen.go
添加FindList方法
userModel interface {
Insert(ctx context.Context, data *User) (sql.Result, error)
FindOne(ctx context.Context, id int64) (*User, error)
FindOneByMobile(ctx context.Context, mobile string) (*User, error)
FindList() ([]*User, error) // 新增
Update(ctx context.Context, newData *User) error
Delete(ctx context.Context, id int64) error
}
// 实现
func (m *defaultUserModel) FindList() ([]*User, error) {
var resp []*User
query := fmt.Sprintf("select %s from %s ", userRows, m.table)
err := m.QueryRowsNoCache(&resp, query)
switch err {
case nil:
return resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
4、rpc 业务逻辑实现
rpc 层重点关注rpc/internal/logic 目录,内是业务的真正实现
以查所有用户为例
func (l *ListUserLogic) ListUser(in *user.ListUserRequest) (*user.ListUserResponse, error) {
results, err := l.svcCtx.UserModel.FindList()
if err != nil {
if err == model.ErrNotFound {
return nil, status.Error(100, "用户不存在")
}
return nil, status.Error(500, err.Error())
}
resp := make([]*user.UserInfoResponse, 0, len(results))
for _, item := range results {
resp = append(resp, &user.UserInfoResponse{
Id: item.Id,
Name: item.Name,
Gender: item.Gender,
Mobile: item.Mobile,
})
}
return &user.ListUserResponse{
Data: resp,
}, nil
}
5、go-zero的proto 书写
在proto中如果func 没有参数,不能:grpc-go protobuf Empty ,而是定位为空message
6、对于go-zero的还需改造点
1、配置文件读取环境变量
2、设置context的超时时间
3、将go-zero里的rpc和api分别build成可执行程序
4、等
总结
总的来说go-zero使用起来有一些束缚 ,不如micro 灵活随意。不可否认的是go-zero封装的相对更好,使开发者基本只用关注业务逻辑。
在业务全面容器化及以istio为主的服务治理越来越主流的当下及未来:个人觉得在代码层面实现服务治理能力似乎不能算是一种优势。其实在以kubernetes 为标准的容器深度发展的当下,客人认为开发者应该回到重点关注业务的实现逻辑,而治理应下移到基础设施层,即Kubernetes + 业务 + 服务治理(istio) 。
标签:string,demo,json,zero,api,user,go 来源: https://www.cnblogs.com/zisefeizhu/p/16434695.html