Go學習【02】:理解Gin,搭一個web demo

飛翔的風箏發表於2021-09-23

Go Gin 框架

說Gin是一個框架,不如說Gin是一個類庫或者工具庫,其包含了可以組成框架的元件。這樣會更好理解一點。

舉個?

下面的示例程式碼在這:github https://github.com/lpgyouxi/gogo
利用Gin組成最基本的框架。說到框架,我們可以先列舉下需要的(最基本)元件,主要四塊,以及下面的重點。

  • 埠監聽
    • 用於監聽請求,也就是服務
  • 請求處理
    • 請求分發
    • 結果處理
  • 路由
    • 路由編寫
    • 路由接入
  • 業務處理
    • 寫一個demo

好,開搞!

前提
* 你已經安裝好go環境,沒安裝的可以百度下,教程很多
* 你已經安裝了Gin,如果沒安裝,安裝命令:go get -u github.com/gin-gonic/gin
// Github上有https://github.com/gin-gonic/gin,大牛直接看這個不用看下面的了
* 建一個專案資料夾 gogo
* 初始化環境go  mod init 模組名或者專案名 
// 比如我把這個測試專案取名為 gogo ; go  mod init gogo

埠監聽

埠監聽: 主要是監聽埠的訊息,提供服務入口。

檔案位置:~/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")  //注意:gin.Context 、引數獲取
		c.JSON(http.StatusOK, gin.H{
			"message": "hello 測試通過",
			"data":param,
		})
	})
	server.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

---------------------------
// 注意上面標識“注意”的行,後面可能會用到
// http://127.0.0.1:8080/?name=123456789
{
  data: "123456789",
  message: "hello 測試通過"
}

為了框架的整體連貫性,後面會對其優化。

請求處理

請求與返回可以看成業務處理的前置和後置部分,一般分為兩部分request和response,即 請求處理和返回處理,如下:

從這裡我將程式碼統一放到web的app目錄下,具體路徑如下

請求處理

~/gogo/app/distribute/request.go

package distribute


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

/**
分配:連結上下文
link context
*/

// 定義一個接受引數的函式型別
type AppReqestFunc func(*AppReqest)

//定義引數結構體
type AppReqest struct {
	 *gin.Context
}

/* 
定義引數賦予方法  
*/
func Handle(r AppReqestFunc) gin.HandlerFunc {
	// gin.HandlerFunc 理解為一種可操作的函式介面,匿名函式
	return func(c *gin.Context) {
		r(&AppReqest{c})
	}
}

/* 
定義引數獲取法  
*/

//定義獲取get引數
func (params AppReqest) InputGet(paramName string) string {
	return params.DefaultQuery(paramName, "")
}


/* 
定義返回方法 
*/

//成功返回
func (c *AppReqest) Success(data interface{}) {
	c.JSON(Success(data))
}

Handle定義了需要接受一個函式型別AppReqestFunc func(*AppReqest),其中引數滿足AppReqest

會返回一個gin.HandlerFunc型別,這個型別適用於Gin的路由引數型別(即gin可呼叫)。

這裡Handle可以做一些自定義的擴充套件。

返回處理

~/gogo/app/distribute/response.go

package distribute


import (
	"github.com/gin-gonic/gin"
	"net/http"  
	"reflect"  // 物件操作的類
)

/**
成功返回,你可以建其它返回,如失敗、錯誤
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": "請求成功",
		}
	} else {
		return http.StatusOK, gin.H{
			"code":    http.StatusOK,
			"data":    data,
			"message": "請求成功",
		}
	}
}

一個返回格式,大致瞭解就行,可以自行豐富。

總結:上面兩個檔案分別是如何接受請求頭,和返回的格式,注意下引數賦予方法 這個可能不好理解,可以在紙上面畫畫,方便理解。

路由

路由編寫

為了以後的路由擴充套件,將server中的路由單獨存放,程式碼如下:

~/gogo/app/routes/api.go

package routes

import (
    "github.com/gin-gonic/gin"
  //  "gogo/app/http"       //業務模組
    "gogo/app/distribute"
)

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


路由還可以分組,分檔案,這裡就不過多描述了,可以自己想想怎麼擴充套件。

上面的e.GET可以按自己的需求進行編寫,這裡是舉了個?

路由接入

為了將路由使用到專案中,需要一箇中間銜接的檔案,實現方式為新增一個啟動檔案,將啟動服務時需要載入的檔案或功能載入進來。

~/gogo/app/boot/bootstrap.go

package boot

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

// 啟動入口
func Bootstrap(c *gin.Engine) {
	SetRoute(c)
}

// 路由入口
func SetRoute(c *gin.Engine) {
	routes.Route(c)
}

這裡將上面路由檔案載入進來了,現在改造服務檔案,加這個檔案載入進去。

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 測試通過",
	// 		"data":param,
	// 	})
	// })

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

和最前面的對比,可以看見,將路由替換為了:boot.Bootstrap(server),進行載入路由檔案。

業務處理

一個業務demo

注意前面路由檔案,有個路由如下

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

將其全部開啟;同時可以看到頭部的引入:"gogo/app/http" ;所以下面看看業務檔案怎麼編寫:

~/gogo/app/http/test.go

package httpimport (	"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 測試通過",		})}

上面的Hello和Test就是業務程式碼塊,展示了返回的方式success即是上面說到的返回處理。如果是複雜邏輯可以將詳細的業務程式碼引入到這裡,就不贅述了。

測試例子

http://127.0.0.1:8080/hello
-----------------------------------
{
  code: 200,
  data: [ ],
  message: "請求成功"
}

新增方法

例子:

gogo/app/routes/api.go增加路由

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

gogo/app/http/test.go增加業務程式碼

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

請求

http://127.0.0.1:8080/get?name=Lucy
-----------------------------------
{
  code: 200,
  data: [
  "Lucy"
  ],
  message: "請求成功"
}

至此,一個微型的例子就完成了。目錄結構如下:

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

結束

基礎的學習go web,深入的話還是需要實踐。

上面的程式碼在這:github

嗯,真的結束了!

相關文章