1. A brief introduction

⚜️ This project is better in these two days, I came into contact with GO and wanted to realize a GO version of Koa for fun. Here, I just realized the core idea of Koa, onion model and simple routing middleware, and other things have not been further carried out.

πŸ‘‰ Warehouse address: Koa for Go welcome to Star

2. Project structure

Let’s take a look at the directory tree structure and functional partitioning of the project

Prompt Exercises - Prompt Exercises - Application. Go koaPrompt Exercises - Prompt Exercises - Application. Go β”‚ β”œβ”€ β”œβ”€ β”œ.go β”‚ β”œβ”€ β”œ.go β”œβ”€ β”œβ”€ β”œβ”€ GET, GET, GET, GET, GET, GET, GET, GET, GET β”œ ─ β”œ ─ └─ β”œ ─ imp. Go //Copy the code

3. Implementation

In fact, Go is a strongly typed language, so when I first tried to come to Go with koa.js, IT didn’t work at all. I’ve only been in Go for a couple of days and I know how to write Go so it was hard to get started with a bunch of bad code.

3.1 Implementation of KOA. JS Onion model

I’m going to post the code for koa.js so we can look at the main ways that koa.js is implemented

As you can see from the code above, the main implementation of the Onion model in KOa.js is quite simple.

First of all, there is a lot of judgment going on, whether the parameters are arrays, whether the elements in the array are functions, but that’s not important for what we’re going to do now.

The compose function returns a function that provides an external call, which is the entry point to start running the middleware.

The compose function also contains a dispatch function, which is the core function for implementing the Onion model. The dispatch function is called recursively. Each call takes one middleware from the middleware set and calls it, recursively passing the next middleware as the next parameter to the current middleware.

3.2 Specific methods of Go to realize onion model

Come to the Go side, I began to copy the way, write is written out is not run at all πŸ§…, according to the Onion model according to the middleware execution order should be 1 -> 2 -> 3 -> 2 -> 1. However goose 🦒 I realized the implementation of the 3 -> 2 -> 1 emmmm ~ ~ this is uncomfortable, temporarily did not understand is for, probably because JS and Go implementation mechanism is not the same.

And then I did a bunch of different things and I ended up using linked lists to implement the Onion model, so much nonsense, ok! In the code.

— ./koa/compose.go

In the comments, the core of the list implementation is the MiddlewareType structure

— ./koa/application.go row:30

Anyway, it’s the simplest linked list structure. Now let’s look at context.

— ./koa/context.go

Context, because of the time, there’s not a lot of encapsulation, it’s just a simple combination of things to form the Context structure.

It implements a Next method on the Context, which basically implements the Next middleware operation, loads the middleware list into the Next one, waits for the Next call, and does nothing if the Next middleware is empty.

It’s basically the above components that support the implementation of my Koa for Go Onion model.

Because the contact time of Go is too short, did not carry on the in-depth study to understand the other SAO operation of Go can only be realized in accordance with their own imagination, the majority of elder brother comment area points out, thank you very much.

3.3 Entry Method

Ok, stickers first

— ./koa/application.go

The main things are written in the notes, so just read the notes. “Application. Go” “Use” and “compose. Go” “Use” “compose.

3.4 Router Middleware

This is actually a simple implementation of the distribution of the route, interested in their own to see the source code, should not be difficult. If you need me to explain more, please leave a comment in the comments section. If you need me to write a separate introduction.

4. Usage

Finish the source code, now say how to use it. I personally feel that the usage is similar to koa.js.

4.1 Simple Applications

You instantiate a Koa and then you write your own middleware implementation, and the middleware receives a Context that has a Next method that can call the Next middleware and then you listen on the port and you start an HTTP service, and you implement the Onion model,

Here I have three middleware

Firstly, according to the known reason of onion model 1 -> 2 -> 3 -> 2 -> 1, we know that the code after Next is called by the first middleware will be called at the end. Therefore, I call Response.Write after the first middleware to return the Body data.

Second, simply set the Body data

Third, since the Body is a structure, we usually return a JSON structure to the front end, so here the structure is transformed and assigned to the JsonBody so that the first middleware can return data.

func main(a) {
    app := koa.Koa{}
    
    // Write data to return
	app.Use(koa.MiddlewareType{ Action: func(context *koa.Context) {
		context.Next()
		context.Response.Write(context.JsonBody)
	}})

	// Load the return information into the body
	app.Use(koa.MiddlewareType{ Action: func(context *koa.Context) {
		context.Body = VO{ Message: "hello koa for go!" }
		context.Next()
	}})

	// Convert the returned object into a JSON object
	app.Use(koa.MiddlewareType{ Action: func(context *koa.Context) {
		context.JsonBody, _ = json.Marshal(context.Body)
	}})
	
	app.Listen(5000) // Listen on port 5000
}
Copy the code

This is a simple application. Now go to your browser and open http://localhost:5000/ to successfully request and return a message

{
  "Message": "hello koa for go!"
}
Copy the code

4.2 use the Router

The above is simple, but there is still a problem that there is no way to match different routes to different functions. This is where routing comes in.

Here is a chestnut using routing 🌰

With a lot more than the above the 🌰 point is how to instantiate a routing structure, inside this structure to achieve the common GET, POST, Put, DELETE these a few commonly used way of request to provide call, respectively to the routing/home I Put here this several requests are implemented, Then the message returned is different.

Calling router.ToMiddleware at the end of the call will return a koa of go intermediate. This route will be applied as soon as it is mounted to the app.

func main(a) {
    app := koa.Koa{}
    router := router.Router{}
    router.Get("/home".func(context *koa.Context) {
        context.Body = success(MessageData{ Info: "hello this is home Get"})
    })
    router.Post("/home".func(context *koa.Context) {
        context.Body = success(MessageData{ Info: "hello this is home Post"})
    })
    router.Put("/home".func(context *koa.Context) {
        context.Body = success(MessageData{ Info: "hello this is home Put"})
    })
    router.Delete("/home".func(context *koa.Context) {
        context.Body = success(MessageData{ Info: "hello this is home Delete"})})// Write data to the response
    app.Use(koa.MiddlewareType{ Action: func(context *koa.Context) {
        context.Next()
		context.JsonBody, _ = json.Marshal(context.Body)
        context.Response.Write(context.JsonBody)
    }})
    // Load the route
    app.Use(router.ToMiddleware())
    app.Listen(5000)}Copy the code

5. Conclusion

Ok above is this time I want to introduce Koa fo Go all the content, as a serious node programmer I am now the main business is C# now Go actually not too much in-depth, so where there is a problem also please give us a lot of advice.

After writing this Koa for Go, I feel like I can do Go again, but I think this is just my illusion.

Thank you for watching ~ ~ thank you!

Your praise is my motivation to update, I will do things for you from time to time to bring interesting fun things ~