golang - 框架实战(go-zero)
golang框架实战(go-zero)
以前我用最习惯用的API框架是gin,由于各家公司都有高人坐镇,所以并不是gin这门武艺一统江湖。
我来这家公司就是以go-zero统一内部所有项目,不仅用了API功能,还使用了RPC进行微服务接入。那么我现在把一场实战演示出来。
项目创建
我使用当时最新版go-zero标签:v1.9.0,如果已经有新版的建议用新版的,很大因素是新版本会修复一些旧版本问题,就比如nacos-sdk-go(项目一直用的时候有个问题,虽然影响不大,但是需要自身业务逻辑去处理,我接手后才进行了版本升级)。
1
https://github.com/zeromicro/go-zero/tree/v1.9.0
首先照着安装goctl ,其他的可以按照官方教程,也可以使用我的习惯(跟网上还是有区分)。
1
2
3
4
5
6
go mod init gozero-api
mkdir api-file && cd api-file
touch demo.api
goctl api go -api demo.api -dir ..
cd ../
go mod tidy
文件内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
syntax = "v1"
//goctl api go -api demo.api -dir ..
info (
title: "我的一个demo"
data: "2025-09-25"
)
import (
"result.api"
)
type (
DemoReq {
Say string `json:"say"` //要发送的文字
}
)
@server (
group: api/demo
middleware: ApiMiddleware,AuthMiddleware
)
service main {
@doc (
summary: "一个demo"
)
@handler say
post /api/demo/say/:name (DemoReq) returns (ResultResp)
}
1
2
3
4
5
6
7
8
9
syntax = "v1"
//ResultResp 统一返回结果
type ResultResp {
Code int `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
项目改造
通过上文我们简单创建了一个api项目,包含了路由层handler、逻辑层 logic。缺少服务层(业务服务、数据服务等)
端口默认8888 (./etc/main.yaml有配置)
以下是个人建议的方式,并非一定按照我的思路,可以借鉴下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 在项目根目录进行目录创建,目录名称个人习惯而定,我定义了comm、doc、model、service
# comm 公共依赖包自研目录
# 例如 mkdir -p comm/defines 存放内部的常量值
mkdir comm
# doc 项目有需求对底层数据结构发生重大变更时,补充文档说明,例如sql的表结构变更
mkdir doc
# model 存放数据实体,仅仅实体的定义用于ORM中的M,最好内部增加包区分(便于按照数据作用域区分)
# 例如 mkdir -p model/uc 存放的都是用户中心(user center)相关的实体
mkdir model
# service 实际服务层
# 例如 mkdir -p service/iuc 用来提供用户中心内部服务,里面包含业务服务和数据服务
# 同时可以增加自己的DML层、DAL层
mkdir service
有朋友建议我把这些放到internal目录下,理由:倘若我们api项目被其他项目引入,这样自己的业务和数据都能得到很好的保护(指的引用方式)。
我的建议是:这个api项目是你们自己的项目,若让另一个api或者web项目引入,那这个应当剥离出一个公共库项目使用,不含对外提供服务的业务逻辑在里面。
朋友又跟我说:好不容易写好的model、comm,我想再另一个项目中用,那怎么办呢?
我的建议:重新申请一个公共lib项目,把这些放到里面进行统一维护。例如我们原来都是单体项目,后来要改成微服务,那就得把公共的抽离出来了(一生二,二生三,三生万物)。一个小项目发展成为一个大集团合作项目 – 生态。
项目继续改造:
把单一多人共同频繁操作的文件,改成独立编辑的文件。
把
internal/types/types.go拆出来:1 2 3 4 5 6
tree internal/types/ -- internal/types/ |-- type.go |-- response.go |-- demo.go |-- uc.go多人共同开发新业务,新增接口或者修改接口协议时,减少冲突范围
把
internal/handler/routes.go拆出来:1 2 3 4 5 6
tree internal/handler/ -- internal/handler/ |-- routes.go |-- routes_demo.go |-- routes_uc.go废弃使用
internal/config/config.go,放到comm/conf/config.go,可以增加全局变量便于其他位置直接使用。
日志改造
项目框架自带access日志,你可以想象一下nginx的日志,会记录每一条请求。
但是我们的Request和Respnse都是放在content中,并没有实现json列的方式,想要搜集到es,需要logstash进行读取然后json化,我这边进行了直接改造,便于filebeat采集。
我们可以增加一个accessMiddlerware,或者logMiddlerware。然后处理我们的上下文数据。