最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang中g(shù)in框架綁定解析json數(shù)據(jù)的兩種方法

 更新時間:2023年12月25日 10:14:53   作者:李遲  
本文介紹 Golang 的 gin 框架接收json數(shù)據(jù)并解析的2種方法,文中通過代碼示例介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

本文介紹 Golang 的 gin 框架接收json數(shù)據(jù)并解析的2種方法。

起因及排查

某微服務(wù)工程,最近測試發(fā)現(xiàn)請求超時,由于特殊原因超時較短,如果請求處理耗時超過1秒則認(rèn)為失敗。排查發(fā)現(xiàn),可能是gin接收解析json數(shù)據(jù)存在耗時,代碼使用ctx.ShouldBindJSON直接解析得到所需結(jié)構(gòu)體,然后通過自實(shí)現(xiàn)的FormatJsonStruct函數(shù)格式化并輸出到日志。該格式函數(shù)如下:

func FormatJsonStruct(str interface{}, format bool) (ret string) {
	ret = ""
	jsonstr, err := json.Marshal(str)
	if err != nil {
		return
	}
	if format {
		var out bytes.Buffer
		_ = json.Indent(&out, []byte(jsonstr), "", "    ")
		ret = out.String()
	} else {
		ret = string(jsonstr)
	}

	return
}

從上述過程看到,先是調(diào)用了ShouldBindJSON,再調(diào)用了Marshal函數(shù)解析成字符串。于是考慮調(diào)用ReadAll讀取數(shù)據(jù),再用Unmarshal解析成結(jié)構(gòu)體,直接輸出結(jié)構(gòu)體數(shù)據(jù)。下面模擬2種不同的解析josn方法。

模擬程序

本節(jié)結(jié)合代碼,簡單描述模擬程序。詳見文附錄。

一般地,在gin中,業(yè)務(wù)處理函數(shù)帶有*gin.Context參數(shù),如本文的HandleGinShouldBindJSON,使用ctx.ShouldBindJSON(&request)將ctx中帶的數(shù)據(jù)直接轉(zhuǎn)換成目標(biāo)結(jié)構(gòu)體。

也可以通過ioutil.ReadAll(ctx.Request.Body)先讀取客戶端來的數(shù)據(jù),由于約定為json格式數(shù)據(jù),所以可以用json.Unmarshal解析成結(jié)構(gòu)體。

無法哪種方法,其實(shí)都很方便,相對而言,前者更便捷。

測試結(jié)果

使用curl模擬請求命令,示例如下:

curl http://127.0.0.1:9000/foo -X POST -H "Content-Type:application/json" -d  '{"id":"test_001", "op":"etc", "timestamp":12342134341234, "data":{"name":"foo", "addr":"bar", "code":450481, "age":100}}'

curl http://127.0.0.1:9000/bar -X POST -H "Content-Type:application/json" -d  '{"id":"test_001", "op":"etc", "timestamp":12342134341234, "data":{"name":"foo", "addr":"bar", "code":450481, "age":100}}'

服務(wù)端輸出日志:

=== RUN   TestGin
test of gin
run gin
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.        
 - using env:   export GIN_MODE=release
 - using code:  gin.SetMode(gin.ReleaseMode)

[GIN-debug] POST   /foo                      --> webdemo/test/gin_test.HandleGinShouldBindJSON (1 handlers)
[GIN-debug] POST   /bar                      --> webdemo/test/gin_test.HandleGinUnmarshal (1 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :9000
ShouldBindJSON: request: #{test_001 etc 12342134341234 {foo bar 450481 100}}
Unmarshal request: #{test_001 etc 12342134341234 {foo bar 450481 100}}
exit status 0xc000013a

小結(jié)

就目前測試和修改結(jié)果看,本文所述方法并非主因,真正原因待查。

附完整代碼

/*
結(jié)構(gòu)體
{
    "id": "test_001",
    "op": "etc",
    "timestamp": 12342134341234,
    "data": {
        "name": "foo",
        "addr": "bar",
        "code": 450481,
        "age": 100
    }
}

curl http://127.0.0.1:9000/foo -X POST -H "Content-Type:application/json" -d  '{"id":"test_001", "op":"etc", "timestamp":12342134341234, "data":{"name":"foo", "addr":"bar", "code":450481, "age":100}}'

curl http://127.0.0.1:9000/bar -X POST -H "Content-Type:application/json" -d  '{"id":"test_001", "op":"etc", "timestamp":12342134341234, "data":{"name":"foo", "addr":"bar", "code":450481, "age":100}}'

*/

package test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"strings"
	"testing"

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

var g_port string = "9000"

type MyRequest_t struct {
	Id        string    `json:"id"`
	Op        string    `json:"op"`
	Timestamp int       `json:"timestamp"`
	Data      ReqData_t `json:"data"`
}

type ReqData_t struct {
	Name string `json:"name"`
	Addr string `json:"addr"`
	Code int    `json:"code"`
	Age  int    `json:"age"`
}

func routerPost(r *gin.Engine) {
	r.POST("/foo", HandleGinShouldBindJSON)
	r.POST("/bar", HandleGinUnmarshal)
}

func initGin() {
	fmt.Println("run gin")
	router := gin.New()
	routerPost(router)

	router.Run(":" + g_port)
}

func HandleGinShouldBindJSON(ctx *gin.Context) {
	var request MyRequest_t
	var err error
	ctxType := ctx.Request.Header.Get("Content-Type")
	if strings.Contains(ctxType, "application/json") { // 純 json
		// 先獲取總的json
		if err = ctx.ShouldBindJSON(&request); err != nil {
			fmt.Printf("ShouldBindJSON failed: %v\n", err)
			return
		}

		fmt.Printf("ShouldBindJSON: request: #%v\n", request)
	} else {
		fmt.Println("非json")
		return
	}
}

func HandleGinUnmarshal(ctx *gin.Context) {
	var request MyRequest_t
	var err error
	var reqbuffer []byte
	ctxType := ctx.Request.Header.Get("Content-Type")
	if strings.Contains(ctxType, "application/json") { // 純 json

		reqbuffer, err = ioutil.ReadAll(ctx.Request.Body)
		if err != nil {
			fmt.Printf("ReadAll body failed: %v\n", err)
			return
		}
		err = json.Unmarshal(reqbuffer, &request)
		if err != nil {
			fmt.Printf("Unmarshal to request failed: %v\n", err)
			return
		}
		fmt.Printf("Unmarshal request: #%v\n", request)
	} else {
		fmt.Println("非json")
		return
	}
}

func TestGin(t *testing.T) {
	fmt.Println("test of gin")

	initGin()
}

以上就是Golang中g(shù)in框架綁定解析json數(shù)據(jù)的兩種方法的詳細(xì)內(nèi)容,更多關(guān)于Golang gin綁定解析json的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • golang結(jié)構(gòu)化日志log/slog包之slog.Record的用法簡介

    golang結(jié)構(gòu)化日志log/slog包之slog.Record的用法簡介

    這篇文章主要為大家詳細(xì)介紹了golang結(jié)構(gòu)化日志log/slog包中slog.Record結(jié)構(gòu)體的使用方法和需要注意的點(diǎn),文中的示例代碼講解詳細(xì),需要的可以學(xué)習(xí)一下
    2023-10-10
  • Win10系統(tǒng)下Golang環(huán)境搭建全過程

    Win10系統(tǒng)下Golang環(huán)境搭建全過程

    在編程語言的選取上,越來越多的人選擇了Golang,下面這篇文章主要給大家介紹了關(guān)于Win10系統(tǒng)下Golang環(huán)境搭建的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • 淺析Go語言中數(shù)組的這些細(xì)節(jié)

    淺析Go語言中數(shù)組的這些細(xì)節(jié)

    這篇文章主要為大家詳細(xì)介紹了Go語言中數(shù)組一些細(xì)節(jié)的相關(guān)資料,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Go語言有一定的幫助,需要的可以了解一下
    2022-11-11
  • Go框架三件套Gorm?Kitex?Hertz基本用法與常見API講解

    Go框架三件套Gorm?Kitex?Hertz基本用法與常見API講解

    這篇文章主要為大家介紹了Go框架三件套Gorm?Kitex?Hertz的基本用法與常見API講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2023-02-02
  • Golang文件讀寫操作詳情

    Golang文件讀寫操作詳情

    這篇文章主要介紹了Golang文件讀寫操作詳情,文件是數(shù)據(jù)源(保存數(shù)據(jù)的地方)的一種,文件最主要的作用就是保存數(shù)據(jù),文件在程序中是以流的形式來操作的,更多詳細(xì)內(nèi)容需要的朋友可以參考一下
    2022-07-07
  • Go語言常見錯誤之誤用init函數(shù)實(shí)例解析

    Go語言常見錯誤之誤用init函數(shù)實(shí)例解析

    Go語言中的init函數(shù)為開發(fā)者提供了一種在程序正式運(yùn)行前初始化包級變量的機(jī)制,然而,由于init函數(shù)的特殊性,不當(dāng)?shù)厥褂盟赡芤鹨幌盗袉栴},本文將深入探討如何有效地使用init函數(shù),列舉常見誤用并提供相應(yīng)的避免策略
    2024-01-01
  • 詳解Golang time包中的結(jié)構(gòu)體time.Time

    詳解Golang time包中的結(jié)構(gòu)體time.Time

    在日常開發(fā)過程中,會頻繁遇到對時間進(jìn)行操作的場景,使用 Golang 中的 time 包可以很方便地實(shí)現(xiàn)對時間的相關(guān)操作,本文先講解一下 time 包中的結(jié)構(gòu)體 time.Time,需要的朋友可以參考下
    2023-07-07
  • Golang中實(shí)現(xiàn)類似類與繼承的方法(示例代碼)

    Golang中實(shí)現(xiàn)類似類與繼承的方法(示例代碼)

    這篇文章主要介紹了Golang中實(shí)現(xiàn)類似類與繼承的方法,Go語言中通過方法接受者的類型來決定方法的歸屬和繼承關(guān)系,本文通過示例代碼講解的非常詳細(xì),需要的朋友可以參考下
    2024-04-04
  • Go中各種newreader和newbuffer的使用總結(jié)

    Go中各種newreader和newbuffer的使用總結(jié)

    這篇文章主要為大家詳細(xì)介紹了Go語言中各種newreader和newbuffer的使用的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的參考價值,感興趣的小伙伴可以了解下
    2023-11-11
  • Go?處理大數(shù)組使用?for?range?和?for?循環(huán)的區(qū)別

    Go?處理大數(shù)組使用?for?range?和?for?循環(huán)的區(qū)別

    這篇文章主要介紹了Go處理大數(shù)組使用for?range和for循環(huán)的區(qū)別,對于遍歷大數(shù)組而言,for循環(huán)能比for?range循環(huán)更高效與穩(wěn)定,這一點(diǎn)在數(shù)組元素為結(jié)構(gòu)體類型更加明顯,下文具體分析感興趣得小伙伴可以參考一下
    2022-05-05

最新評論

武清区| 涞源县| 巩留县| 彭水| 临朐县| 厦门市| 盖州市| 清原| 萨嘎县| 昌宁县| 常德市| 兴文县| 枣强县| 诏安县| 海伦市| 玛曲县| 阿勒泰市| 临城县| 鸡东县| 海城市| 汝阳县| 垦利县| 尤溪县| 淮南市| 台江县| 鄂托克旗| 阿坝| 许昌市| 宁海县| 鸡泽县| 龙南县| 当雄县| 定结县| 八宿县| 永丰县| 邵阳县| 舟曲县| 万载县| 长治县| 许昌县| 积石山|