一、golang环境安装及配置go module
https://go-zero.dev/cn/docs/prepare/golang-install
mac os安装go#
- 下载并安装go for mac
- 验证安装结果
$ go version go version go1.15.1 darwin/amd64
linux 安装go#
- 下载go for linux
- 解压压缩包至/usr/local
$ tar -c /usr/local -xzf go1.15.8.linux-amd64.tar.gz
添加/usr/local/go/bin到环境变量
$ $home/.profile $ export path=$path:/usr/local/go/bin $ source $home/.profile
验证安装结果
$ go version go version go1.15.1 linux/amd64
windows安装go#
下载并安装go for windows验证安装结果
$ go version go version go1.15.1 windows/amd64
module配置
go module是golang管理依赖性的方式,像java中的maven,android中的gradle类似。
查看go111module开启情况
$ go env go111module on
开启go111module,如果已开启(即执行go env go111module结果为on)请跳过。
$ go env -w go111module="on"
设置goproxy
$ go env -w goproxy=https://goproxy.cn
设置gomodcache
查看gomodcache
$ go env gomodcache
如果目录不为空或者/dev/null,请跳过。
go env -w gomodcache=$gopath/pkg/mod
二、goctl 安装
goctl在go-zero项目开发着有着很大的作用,其可以有效的帮助开发者大大提高开发效率,减少代码的出错率,缩短业务开发的工作量,更多的goctl的介绍请阅读goctl介绍
安装(mac&linux)
### go 1.15 及之前版本 go111module=on goproxy=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero/tools/goctl@latest ### go 1.16 及以后版本 goproxy=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/goctl@latest
安装(windows)
go install github.com/zeromicro/go-zero/tools/goctl@latest
环境变量检测(mac&linux)
go get 下载编译后的二进制文件位于 $gopath/bin 目录下,要确保 $gopath/bin已经添加到环境变量。
sudo vim /etc/paths //添加环境变量
在最后一行添加如下内容 //$gopath 为你本机上的文件地址
$gopath/bin
安装结果验证
$ goctl -v goctl version 1.1.4 darwin/amd64
二、初始化go-zero
快速生成 api 服务
goctl api new greet cd greet go mod init go mod tidy go run greet.go -f etc/greet-api.yaml
greet-api.yamlhttp://localhost:8888/from/you
$ curl -i http://localhost:8888/from/you http/1.1 200 ok content-type: application/json; charset=utf-8 traceparent: 00-45fa9e7a7c505bad3a53a024e425ace9-eb5787234cf3e308-00 date: thu, 22 oct 2020 14:03:18 gmt content-length: 14 null
greet服务的目录结构
$ tree greet greet ├── etc │ └── greet-api.yaml ├── greet.api ├── greet.go └── internal ├── config │ └── config.go ├── handler │ ├── greethandler.go │ └── routes.go ├── logic │ └── greetlogic.go ├── svc │ └── servicecontext.go └── types └── types.go
三、查看注册handler路由流程greet.go
var configfile = flag.string("f", "etc/greet-api.yaml", "the config file") func main() { flag.parse() var c config.config conf.mustload(*configfile, &c) server := rest.mustnewserver(c.restconf) defer server.stop() //上面的都是加载配置什么的 ctx := svc.newservicecontext(c) handler.registerhandlers(server, ctx) //此方法是注册路由和路由映射handler,重点在这里 fmt.printf("starting server at %s:%d...n", c.host, c.port) server.start() }
internalhandlerroutes.go
func registerhandlers(server *rest.server, serverctx *svc.servicecontext) { server.addroutes( //往rest.server中添加路由 []rest.route{ //路由数组 { method: http.methodget, path: "/from/:name", //路由 handler: greethandler(serverctx),//当前路由的处理handler }, }, ) }
internalhandlergreethandler.go
func greethandler(ctx *svc.servicecontext) http.handlerfunc { return func(w http.responsewriter, r *http.request) { var req types.request if err := httpx.parse(r, &req); err != nil { //请求的错误判断,这个可以不用管 httpx.error(w, err) return } l := logic.newgreetlogic(r.context(), ctx) //greethandler处理函数将请求转发到了greetlogic中,调用newgreetlogic进行结构体的初始化 resp, err := l.greet(req) //然后调用greet来进行处理请求,所以我们在greetlogic.greet方法中可以看到一句话// todo: add your logic here and delete this line if err != nil { httpx.error(w, err) } else { httpx.okjson(w, resp) } } }
四、对注册handler路由进行简化
项目文件的增加
func xxxxhandler(ctx *svc.servicecontext) http.handlerfunccustomlogic.gointernallogicinternalhandlerroutes.go
{ method: http.methodget, path: "/custom/:name", handler: customhandler(serverctx), },
此时,我们的文件结构应该是这样
greet ├── etc │ └── greet-api.yaml ├── greet.api ├── greet.go └── internal ├── config │ └── config.go ├── handler │ ├── greethandler.go │ ├── customhandler.go │ ├── ... │ └── routes.go ├── logic │ ├── greetlogic.go │ ├── ... │ └── customlogic.go ├── svc │ └── servicecontext.go └── types └── types.go
当单体应用达到一定的数量级,handler和logic文件夹下将会同步增加很多的文件
引入泛型概念
handler: greethandler(serverctx)logic.newgreetlogic(r.context(), ctx)l.greet(req)
internallogicbaselogic.go
package logic import ( "greet/internal/svc" "greet/internal/types" "net/http" ) type baselogic interface { any handler(req types.request, w http.responsewriter, r *http.request, svcctx *svc.servicecontext) //每一个结构体中必须要继承一下handler方法,例如customlogic.go和greetlogic.go中的handler方法 } type logic[t baselogic] struct { data t } func new[t baselogic]() logic[t] { c := logic[t]{} var ins t c.data = ins return c } func (a *logic[t]) logichandler(req types.request, w http.responsewriter, r *http.request, svcctx *svc.servicecontext) { //作为一个中转处理方法,最终执行结构体的handler a.data.handler(req, w, r, svcctx) }
greethandler.gobasehandler.gogreethandler
package handler import ( "net/http" "greet/internal/logic" "greet/internal/svc" "greet/internal/types" "github.com/zeromicro/go-zero/rest/httpx" ) // func greethandler(svcctx *svc.servicecontext) http.handlerfunc { // return basehandlerfunc(svcctx) // // return func(w http.responsewriter, r *http.request) { // // var req types.request // // if err := httpx.parse(r, &req); err != nil { // // httpx.error(w, err) // // return // // } // // l := logic.newgreetlogic(r.context(), svcctx) // // resp, err := l.greet(&req) // // if err != nil { // // httpx.error(w, err) // // } else { // // httpx.okjson(w, resp) // // } // // } // } func basehandlerfunc[t logic.baselogic](svcctx *svc.servicecontext, t t) http.handlerfunc { return func(w http.responsewriter, r *http.request) { var req types.request if err := httpx.parse(r, &req); err != nil { httpx.error(w, err) return } //通过泛型动态调用不同结构体的handler方法 cc := logic.new[t]() cc.logichandler(req, w, r, svcctx) } }
internallogicgreetlogic.gohandler
package logic import ( "context" "net/http" "greet/internal/svc" "greet/internal/types" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/rest/httpx" ) type greetlogic struct { logx.logger ctx context.context svcctx *svc.servicecontext } func newgreetlogic(ctx context.context, svcctx *svc.servicecontext) *greetlogic { return &greetlogic{ logger: logx.withcontext(ctx), ctx: ctx, svcctx: svcctx, } } func (a greetlogic) handler(req types.request, w http.responsewriter, r *http.request, svcctx *svc.servicecontext) { //新增方法 l := newgreetlogic(r.context(), svcctx) resp, err := l.greet(&req) if err != nil { httpx.error(w, err) } else { httpx.okjson(w, resp) } } func (l *greetlogic) greet(req *types.request) (resp *types.response, err error) { // todo: add your logic here and delete this line response := new(types.response) if (*req).name == "me" { response.message = "greetlogic: listen to me, thank you." } else { response.message = "greetlogic: listen to you, thank me." } return response, nil }
internalhandlerroutes.goserver.addroutes
func registerhandlers(server *rest.server, serverctx *svc.servicecontext) { server.addroutes( //往rest.server中添加路由 []rest.route{ //路由数组 { method: http.methodget, path: "/from/:name", //路由 handler: basehandlerfunc(serverctx,logic.greetlogic{}), }, }, ) }
现在就大功告成了,我们启动一下
go run greet.go -f etc/greet-api.yaml
http://localhost:8888/from/you
internallogiccustomlogic.go
package logic import ( "context" "net/http" "greet/internal/svc" "greet/internal/types" "github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/rest/httpx" ) type customlogic struct { logx.logger ctx context.context svcctx *svc.servicecontext } func newcustomlogic(ctx context.context, svcctx *svc.servicecontext) *customlogic { return &customlogic{ logger: logx.withcontext(ctx), ctx: ctx, svcctx: svcctx, } } func (a customlogic) handler(req types.request, w http.responsewriter, r *http.request, svcctx *svc.servicecontext) { l := newcustomlogic(r.context(), svcctx) resp, err := l.custom(&req) if err != nil { httpx.error(w, err) } else { httpx.okjson(w, resp) } } func (l *customlogic) custom(req *types.request) (resp *types.response, err error) { //response.message稍微修改了一下,便于区分 // todo: add your logic here and delete this line response := new(types.response) if (*req).name == "me" { response.message = "customlogic: listen to me, thank you." } else { response.message = "customlogic: listen to you, thank me." } return response, nil }
internalhandlerroutes.go
func registerhandlers(server *rest.server, serverctx *svc.servicecontext) { server.addroutes( //往rest.server中添加路由 []rest.route{ //路由数组 { method: http.methodget, path: "/from/:name", //路由 handler: basehandlerfunc(serverctx,logic.greetlogic{}), }, { method: http.methodget, path: "/to/:name", //路由 handler: basehandlerfunc(serverctx,logic.customlogic{}), }, }, ) }
其他地方不需要修改
我们启动一下
go run greet.go -f etc/greet-api.yaml
http://localhost:8888/from/youhttp://localhost:8888/to/youhttp://localhost:8888/too/you
xxxxhandler.go
python教程分享关于go-zero单体服务使用泛型简化注册Handler路由的问题代码放在go-zero-monolithic-service-generics
到此这篇关于go-zero单体服务使用泛型简化注册handler路由的文章就介绍到这了,更多相关go-zero单体服务内容请搜索<234IT>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<234IT>!
需要了解更多python教程分享关于go-zero单体服务使用泛型简化注册Handler路由的问题,都可以关注python教程分享栏目—234IT(www.234it.com)