当前位置:网站首页>The go zero singleton service uses generics to simplify the registration of handler routes
The go zero singleton service uses generics to simplify the registration of handler routes
2022-07-28 04:51:00 【qq_ forty-three million four hundred and seventy-nine thousand 】
High quality resource sharing
| Learning route guidance ( Click unlock ) | Knowledge orientation | Crowd positioning |
|---|---|---|
| 🧡 Python Actual wechat ordering applet 🧡 | Progressive class | This course is python flask+ Perfect combination of wechat applet , From the deployment of Tencent to the launch of the project , Create a full stack ordering system . |
| Python Quantitative trading practice | beginner | Take you hand in hand to create an easy to expand 、 More secure 、 More efficient quantitative trading system |
One 、Golang Environment installation and configuration Go Module
https://go-zero.dev/cn/docs/prepare/golang-install
mac OS install Go#
- Download and install Go for Mac
- Verify installation results
Copy Highlighter-hljs
| | $ go version |
| | go version go1.15.1 darwin/amd64 |
linux install Go#
- download Go for Linux
- Unzip the package to /usr/local
Copy Highlighter-hljs$ tar -C /usr/local -xzf go1.15.8.linux-amd64.tar.gz
- add to /usr/local/go/bin To environment variable
Copy Highlighter-hljs
| | $ $HOME/.profile |
| | $ export PATH=$PATH:/usr/local/go/bin |
| | $ source $HOME/.profile |
- Verify installation results
Copy Highlighter-hljs
| | $ go version |
| | go version go1.15.1 linux/amd64 |
Windows install Go#
- Download and install Go for Windows
- Verify installation results
Copy Highlighter-hljs
| | $ go version |
| | go version go1.15.1 windows/amd64 |
MODULE To configure
Go Module yes Golang How to manage dependencies , image Java Medium Maven,Android Medium Gradle similar .
- see GO111MODULE Opening situation
Copy Highlighter-hljs
| | $ go env GO111MODULE |
| | on |
- Turn on GO111MODULE, If on ( The perform go env GO111MODULE The result is on) Please skip. .
Copy Highlighter-hljs$ go env -w GO111MODULE="on"
- Set up GOPROXY
Copy Highlighter-hljs$ go env -w GOPROXY=https://goproxy.cn
- Set up GOMODCACHE
Copy Highlighter-hljs see GOMODCACHE
$ go env GOMODCACHE
- If the directory is not empty or /dev/null, Please skip. .
Copy Highlighter-hljsgo env -w GOMODCACHE=$GOPATH/pkg/mod
Two 、Goctl install
Goctl stay go-zero Project development plays a great role , It can effectively help developers greatly improve development efficiency , Reduce the error rate of code , Reduce the workload of business development , added Goctl Please read the introduction of Goctl Introduce
- install (mac&linux)
Copy Highlighter-hljs
| | ### Go 1.15 And previous versions |
| | GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero/tools/[email protected] |
| | |
| | ### Go 1.16 And later versions |
| | GOPROXY=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/[email protected] |
- install (windows)
Copy Highlighter-hljsgo install github.com/zeromicro/go-zero/tools/[email protected]
- Environment variable detection (mac&linux)
go get Download the compiled binary file in $GOPATH/bin Under the table of contents , Make sure $GOPATH/bin Has been added to the environment variable .
Copy Highlighter-hljssudo vim /etc/paths // Add environment variables
Add the following to the last line //$GOPATH It is the file address on your local computer
Copy Highlighter-hljs$GOPATH/bin
- Verification of installation results
Copy Highlighter-hljs
| | $ goctl -v |
| | goctl version 1.1.4 darwin/amd64 |
Two 、 initialization go-zero
Copy Highlighter-hljs
| | goctl api new greet |
| | cd greet |
| | go mod init |
| | go mod tidy |
| | go run greet.go -f etc/greet-api.yaml |
- Default listening is on 8888 port
The listening port can be ingreet-api.yamlModify in the configuration file , here , Can pass curl request , Or open it directly in the browserhttp://localhost:8888/from/you
Copy Highlighter-hljs
| | $ 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 Directory structure of the service
Copy Highlighter-hljs
| | $ 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 |
3、 ... and 、 View registration Handler Routing process
- greet.go
Copy Highlighter-hljs
| | 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() |
| | // The above are loading configurations |
| | ctx := svc.NewServiceContext(c) |
| | handler.RegisterHandlers(server, ctx) // This method is to register routes and route mappings Handler, That's the point |
| | |
| | fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port) |
| | server.Start() |
| | } |
- RegisterHandlers stay
internal\handler\routes.goin
Copy Highlighter-hljs
| | func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { |
| | server.AddRoutes( // Go to rest.Server Add route to |
| | []rest.Route{ // Route array |
| | { |
| | Method: http.MethodGet, |
| | Path: "/from/:name", // route |
| | Handler: GreetHandler(serverCtx),// Processing of current route Handler |
| | }, |
| | }, |
| | ) |
| | } |
- GreetHandler stay
internal\handler\greethandler.goin
Copy Highlighter-hljs
| | func GreetHandler(ctx *svc.ServiceContext) http.HandlerFunc { |
| | return func(w http.ResponseWriter, r *http.Request) { |
| | 1. var req types.Request |
| | 2. if err := httpx.Parse(r, &req); err != nil { // Wrong judgment of request , You don't have to worry about this |
| | 3. httpx.Error(w, err) |
| | 4. return |
| | 5. } |
| | |
| | l := logic.NewGreetLogic(r.Context(), ctx) //GreetHandler The handler forwarded the request to GreetLogic in , call NewGreetLogic Initialize the structure |
| | resp, err := l.Greet(req) // And then call Greet To process requests , So we are GreetLogic.Greet You can see a sentence in the method // todo: add your logic here and delete this line |
| | if err != nil { |
| | httpx.Error(w, err) |
| | } else { |
| | httpx.OkJson(w, resp) |
| | } |
| | } |
| | } |
Four 、 Register for Handler Route simplification
Addition of project documents
During route registration , If we provide more services , So the corresponding func xxxxHandler(ctx *svc.ServiceContext) http.HandlerFunc It needs to be added many times , And inside the method body 1 To 5 Lines belong to additional repeated additions
for example : Let's add a customlogic.go
According to the correctness and standardization of naming , Need to be in internal\logic Add under directory customlogic.go file , And then in internal\handler Add under directory customhandler.go file , And corresponding structures and functions are added to both files , Last in routes.go Add again in
Copy Highlighter-hljs
| | { |
| | Method: http.MethodGet, |
| | Path: "/custom/:name", |
| | Handler: CustomHandler(serverCtx), |
| | }, |
here , Our file structure should be like this
Copy Highlighter-hljs
| | 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 |
When the monomer application reaches a certain order of magnitude ,handler and logic Many files will be added synchronously under the folder
Introduce the concept of generics
since Go1.18 Start ,go Start using generics , A broad definition of generics : It's a special type that postpones the work of defining the type until the object is created or the method is called . In other words, in the process of using generics , The data type of the operation is specified as a parameter , And this parameter type can be used in class 、 Methods and interfaces in , They are called Generic classes 、 Generic methods 、 Generic interface .
We can use generics , Let it be fixed when adding routes Handler: GreetHandler(serverCtx) Put it off until later , According to the actual Logic Structure to judge what needs to be really executed logic.NewGreetLogic(r.Context(), ctx) Initialize structure and l.Greet(req) Logic processing method
How to do it
- stay
internal\logicLet's add onebaselogic.gofile , Reference resources Go Generic combat | How to use generics in structures
Copy Highlighter-hljs
| | 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) // Each structure must inherit Handler Method , for example customlogic.go and greetlogic.go Medium Handler Method |
| | } |
| | |
| | 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) { // As a transit processing method , Finally, execute the Handler |
| | a.data.Handler(req, w, r, svcCtx) |
| | } |
- take
greethandler.goDocument modified tobasehandler.go, Comment out the previousGreetHandlerMethod
Copy Highlighter-hljs
| | 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 |
| | } |
| | // Dynamically call different structures through generics Handler Method |
| | cc := logic.New[T]() |
| | cc.LogicHandler(req, w, r, svcCtx) |
| | } |
| | } |
- stay
internal\logic\greetlogic.goAdd oneHandlerMethod
Copy Highlighter-hljs
| | 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) { // The new method |
| | 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 |
| | } |
- And then modify
internal\handler\routes.goBelowserver.AddRoutespart
Copy Highlighter-hljs
| | func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { |
| | server.AddRoutes( // Go to rest.Server Add route to |
| | []rest.Route{ // Route array |
| | { |
| | Method: http.MethodGet, |
| | Path: "/from/:name", // route |
| | Handler: BaseHandlerFunc(serverCtx,logic.GreetLogic{}), |
| | }, |
| | }, |
| | ) |
| | } |
Now it's done , Let's start
Copy Highlighter-hljsgo run greet.go -f etc/greet-api.yaml
Then request it in the browser http://localhost:8888/from/you
Verify the new api route
- stay
internal\logicNext, add a new onecustomlogic.gofile
Copy Highlighter-hljs
| | 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 A little modification , Easy to distinguish |
| | // 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 |
| | } |
- And then modify
internal\handler\routes.go
Copy Highlighter-hljs
| | func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { |
| | server.AddRoutes( // Go to rest.Server Add route to |
| | []rest.Route{ // Route array |
| | { |
| | Method: http.MethodGet, |
| | Path: "/from/:name", // route |
| | Handler: BaseHandlerFunc(serverCtx,logic.GreetLogic{}), |
| | }, |
| | { |
| | Method: http.MethodGet, |
| | Path: "/to/:name", // route |
| | Handler: BaseHandlerFunc(serverCtx,logic.CustomLogic{}), |
| | }, |
| | }, |
| | ) |
| | } |
Other places don't need to be changed
Let's start
Copy Highlighter-hljsgo run greet.go -f etc/greet-api.yaml
Then request it in the browser http://localhost:8888/from/you、http://localhost:8888/to/you、http://localhost:8888/too/you
Now? , Adding a new logic When doing route mapping , You can simply add xxxxhandler.go The file , In fact, this Handler Moved to xxxxlogic.go in .
Novice , Don't like light spray
The code of this article is placed in
边栏推荐
猜你喜欢

Constructor of member function

Special topic of APP performance design and Optimization - poor implementation affecting performance

Rendering process, how the code becomes a page (2)

Automated test tool playwright (quick start)

Analyze the emotional elements contained in intelligent sweeping robot
![(3.1) [Trojan horse synthesis technology]](/img/e7/0e09c1d1bac23022ead7478ea9898a.png)
(3.1) [Trojan horse synthesis technology]
![[daily question 1] 735. Planetary collision](/img/ba/0ef08ff874f1ddad3fa79b01dba61f.png)
[daily question 1] 735. Planetary collision

Analysis of the reason why easycvr service can't be started and tips for dealing with easy disk space filling
![String 0123456789abcdef, what is the number of substrings (not empty and not the same string itself) [Hangzhou multi tester] [Hangzhou multi tester _ Wang Sir]](/img/78/efe3d70a4bfe8ac0c9b58b54d02b00.png)
String 0123456789abcdef, what is the number of substrings (not empty and not the same string itself) [Hangzhou multi tester] [Hangzhou multi tester _ Wang Sir]

Reading of seq2path: generating sentimental tuples as paths of a tree
随机推荐
[daily one] visual studio2015 installation in ancient times
printf()打印char* str
Transformer landing | next vit realizes the real-time landing of industrial tensorrt, surpassing RESNET and cswin
np. unravel_ Index() finds the index value of an element (or group of elements) of the array after being pulled into one dimension. The corresponding index value in the original dimension (or specify
(克隆虚拟机步骤)
Redis配置文件详解/参数详解及淘汰策略
Use and expansion of fault tolerance and fusing
【sylar】框架篇-Chapter22-辅助模块
你必需要了解的saas架构设计?
[daily question 1] 735. Planetary collision
(2.4) [service Trojan -slimftp] introduction and use
提升学生群体中的STEAM教育核心素养
[Sylar] framework -chapter12 bytearray module
could only be written to 0 of the 1 minReplication nodes. There are 0 datanode(s) running and 0 node
[函数文档] torch.histc 与 paddle.histogram 与 numpy.histogram
[II. Mobile web page development] 2D & 3D conversion and animation, mobile terminal layout, responsive layout
【sylar】框架篇-Chapter7-IO 协程调度模块
gerrit操作-回退掉某个patch_set
Select sorting method
100 lectures on Excel practical application cases (XI) - tips for inserting pictures in Excel