一、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

关于go-zero单体服务使用泛型简化注册Handler路由的问题

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

关于go-zero单体服务使用泛型简化注册Handler路由的问题

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)