Go Learning [02]: Understand Gin, build a web demo

Time:2022-8-17

Go Gin frame

To say that Gin is a framework, it is better to say that Gin is a class library or tool library, which contains components that can form a framework. This will make it a little better to understand.

give

The following sample code is here: github https://github.com/lpgyouxi/gogo
Use Gin to form the most basic framework. When it comes to the framework, we can first list the required (basic) components, the main four, and the following key points.

  • port listening
    • Used to monitor requests, that is, services
  • request processing
    • request distribution
    • result processing
  • routing
    • route writing
    • routed access
  • business processing
    • write a demo

OK, let's do it!

premise
* You have installed the go environment. If you haven't installed it, you can download it from Baidu. There are many tutorials.
* You have installed Gin, if not, install the command: go get -u github.com/gin-gonic/gin
// There is https://github.com/gin-gonic/gin on Github, Daniel can look directly at this without looking at the following
* Create a project folder gogo
* Initialize the environment go mod init module name or project name 
// For example, I named this test project gogo; go mod init gogo

port listening

Port monitoring: It mainly listens to port messages and provides service entry.

File location: ~/gogo/server.go

package main
import (
	"github.com/gin-gonic/gin"
	"net/http"
)


func main()  {
	server := gin.Default()
	server.GET("/", func(c *gin.Context) {
		param := c.DefaultQuery("name", "Guest") //Note: gin.Context, parameter acquisition
		c.JSON(http.StatusOK, gin.H{
			"message": "hello test passed",
			"data":param,
		})
	})
	server.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

---------------------------
// Note the line marked "Attention" above, it may be used later
// http://127.0.0.1:8080/?name=123456789
{
  data: "123456789",
  message: "hello test passed"
}

For the overall coherence of the framework, it will be optimized later.

request processing

Request and return can be regarded as the pre- and post-part of business processing, generally divided into two parts request and response, namely request processing and return processing, as follows:

From here, I put the code in the app directory of the web, and the specific path is as follows

request processing

~/gogo/app/distribute/request.go

package distribute


import (
	"github.com/gin-gonic/gin"
)

/**
Assignment: Link Context
link context
*/

// define a function type that accepts parameters
type AppReqestFunc func(*AppReqest)

//Define the parameter structure
type AppReqest struct {
	 *gin.Context
}

/* 
Define parameter assignment method  
*/
func Handle(r AppReqestFunc) gin.HandlerFunc {
	// gin.HandlerFunc is understood as an operational functional interface, anonymous function
	return func(c *gin.Context) {
		r(&AppReqest{c})
	}
}

/* 
Define parameter acquisition method  
*/

//Define the get parameter
func (params AppReqest) InputGet(paramName string) string {
	return params.DefaultQuery(paramName, "")
}


/* 
define return method 
*/

//successfully return
func (c *AppReqest) Success(data interface{}) {
	c.JSON(Success(data))
}

HandleDefines the type that needs to accept a functionAppReqestFunc func(*AppReqest), where the parameters satisfyAppReqest

will return agin.HandlerFuncType, this type applies to Gin's route parameter type (that is, gin is callable).

hereHandleCan do some custom extensions.

return processing

~/gogo/app/distribute/response.go

package distribute


import (
	"github.com/gin-gonic/gin"
	"net/http"  
	"reflect" // class for object manipulation
)

/**
Returns successfully, you can create other returns, such as failure, error
Successful return, you can create other returns, such as failure and error
*/
func Success(data interface{}) (int, gin.H) {
	ref := reflect.ValueOf(data)
	if ref.IsNil() {
		return http.StatusOK, gin.H{
			"code":    http.StatusOK,
			"data":    make(map[string]interface{}),
			"message": "Request succeeded",
		}
	} else {
		return http.StatusOK, gin.H{
			"code":    http.StatusOK,
			"data":    data,
			"message": "Request succeeded",
		}
	}
}

A return format, a general understanding is enough, and you can enrich it yourself.

Summary: The above two files are how to accept the request header and the format returned, pay attention to the followingparameter assignment methodThis may be difficult to understand, you can draw on paper to facilitate understanding.

routing

route writing

For future routing expansion, the routes in the server are stored separately. The code is as follows:

~/gogo/app/routes/api.go

package routes

import (
    "github.com/gin-gonic/gin"
  // "gogo/app/http" //Business module
    "gogo/app/distribute"
)

func Route(e *gin.Engine) {
  
  	//test
  	e.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "hello",
        })
    })
    // business 
    // test := http.TestController{}
    // e.GET("/test", distribute.Handle(test.Test))
    // e.GET("/hello", distribute.Handle(test.Hello))
}

Routing can also be grouped and divided into files. I won't describe it too much here. You can think about how to expand it yourself.

abovee.GETYou can write it according to your own needs, here is an example

routed access

In order to use the route in the project, an intermediate connection file is required. The implementation method is to add a startup file to load the files or functions that need to be loaded when starting the service.

~/gogo/app/boot/bootstrap.go

package boot

import (
	"github.com/gin-gonic/gin"
	"gogo/app/routes"
)

// start the entry
func Bootstrap(c *gin.Engine) {
	SetRoute(c)
}

// route entry
func SetRoute(c *gin.Engine) {
	routes.Route(c)
}

Here, the above routing file is loaded, and now the service file is modified, and this file is loaded into it.

package main
import (
	"github.com/gin-gonic/gin"
	// "net/http"
	"gogo/app/boot"
)


func main()  {
	server := gin.Default()
  
	boot.Bootstrap(server)
	// server.GET("/", func(c *gin.Context) {
	// 	param := c.DefaultQuery("name", "Guest")
	// 	c.JSON(http.StatusOK, gin.H{
	// "message": "hello test passed",
	// 		"data":param,
	// 	})
	// })

	server.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

Compared with the previous one, you can see that the route is replaced by:boot.Bootstrap(server), to load the routing file.

business processing

A business demo

Note the previous routing file, there is a route as follows

// business 
    // test := http.TestController{} 
    // e.GET("/test", distribute.Handle(test.Test))
    // e.GET("/hello", distribute.Handle(test.Hello))

Turn it all on; at the same time you can see the introduction of the header:"gogo/app/http" ; So let's see how the business file is written:

~/gogo/app/http/test.go

package http
import (	
    "github.com/gin-gonic/gin"	
    "gogo/app/distribute"	
    "fmt"
)
type TestController  struct {}

func (r *TestController) Hello(request *distribute.AppReqest) {	
  fmt.Println("Ok");	
  request.Success(make([]int, 0));
}

func (r *TestController) Test(request *distribute.AppReqest) {
		request.JSON(200, gin.H{
			"message": "hello test passed",
		})
}

The above Hello and Test are business code blocks, showing the way to returnsuccessThat is, the return processing mentioned above. If it is complex logic, detailed business code can be introduced here, so I won't go into details.

test example

http://127.0.0.1:8080/hello
-----------------------------------
{
  code: 200,
  data: [ ],
  message: "The request was successful"
}

new method

example:

gogo/app/routes/api.go add routes

// exp: get 、 param
e.GET("/get", distribute.Handle(test.TestGet))

gogo/app/http/test.go add business code

func (r *TestController) TestGet(request *distribute.AppReqest) {
		var data = []string{}
		var name = request.InputGet("name")
		data = append(data,name)
		request.Success(data);
}

ask

http://127.0.0.1:8080/get?name=Lucy
-----------------------------------
{
  code: 200,
  data: [
  "Lucy"
  ],
  message: "The request was successful"
}

So far, a miniature example is complete. The directory structure is as follows:

|____go.mod
|____server.go
|____app
| |____boot
| | |____bootstrap.go
| |____distribute
| | |____response.go
| | |____request.go
| |____http
| | |____test.go
| |____routes
| | |____api.go
|____LICENSE
|____go.sum
|____README.md

Finish

basic learning go web, In-depth words still need practice.

The above code is here: github

Well, it's really over!