婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > gin解析json格式的數據出錯的處理方案

gin解析json格式的數據出錯的處理方案

熱門標簽:湛江crm外呼系統排名 重慶慶云企業400電話到哪申請 不封卡外呼系統 地圖標注免費定制店 上海極信防封電銷卡價格 鄭州智能語音電銷機器人價格 宿遷便宜外呼系統代理商 仙桃400電話辦理 寧波語音外呼系統公司

寫的接口給測試測試,現在還沒有頁面,直接測試接口。使用

c.BindJSON(req)

總是報錯,大致錯誤信息如下:

err="invalid character '-' in numeric literal"

這是由于我的接口要求將參數按照json格式傳遞到后臺,結果測試同事使用了form-data格式,所以才會有上面這個錯誤。

=============補充2018-11-09 18:20:00=============

剛剛又出現了這個EOF的問題,前端確定已經按照json格式傳參,但是還是有這個問題。

通過wireshark抓包發現,前端給的Content-Length為0,說明沒有將參數傳入后臺。

后來前端核查代碼發現,確實是沒有將參數傳入,只是定義了

補充:gin json 獲取_Gin框架系列 自定義錯誤處理

概述

很多讀者在后臺向我要 Gin 框架實戰系列的 Demo 源碼,在這里再說明一下,源碼我都更新到 GitHub 上,地址:https://github.com/xinliangnote/Go

開始今天的文章,為什么要自定義錯誤處理?默認的錯誤處理方式是什么?

那好,咱們就先說下默認的錯誤處理。

默認的錯誤處理是 errors.New("錯誤信息"),這個信息通過 error 類型的返回值進行返回。

舉個簡單的例子:

func hello(name string) (str string, err error) {
if name == "" {
err = errors.New("name 不能為空")
return
}
str = fmt.Sprintf("hello: %s", name)
return
}

當調用這個方法時:

var name = ""
str, err := hello(name)
if err != nil {
fmt.Println(err.Error())
return
}

這就是默認的錯誤處理,下面還會用這個例子進行說。

這個默認的錯誤處理,只是得到了一個錯誤信息的字符串。

然而...

我還想得到發生錯誤時的 時間、 文件名、 方法名、 行號 等信息。

我還想得到錯誤時進行告警,比如 短信告警、 郵件告警、 微信告警 等。

我還想調用的時候,不那么復雜,就和默認錯誤處理類似,比如:

alarm.WeChat("錯誤信息")
return

這樣,我們就得到了我們想要的信息( 時間、 文件名、 方法名、 行號),并通過 微信 的方式進行告警通知我們。

同理, alarm.Email("錯誤信息")、 alarm.Sms("錯誤信息") 我們得到的信息是一樣的,只是告警方式不同而已。

還要保證,我們業務邏輯中,獲取錯誤的時候,只獲取錯誤信息即可。

上面這些想出來的,就是今天要實現的,自定義錯誤處理,我們就實現之前,先說下 Go 的錯誤處理。

錯誤處理

package main
import (
"errors"
"fmt"
)
func hello(name string) (str string, err error) {
if name == "" {
err = errors.New("name 不能為空")
return
}
str = fmt.Sprintf("hello: %s", name)
return
}
func main() {
var name = ""
fmt.Println("param:", name)
str, err := hello(name)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(str)
}

輸出:

param: Tom

hello: Tom

當 name = "" 時,輸出:

param:

name 不能為空

建議每個函數都要有錯誤處理,error 應該為最后一個返回值。

咱們一起看下官方 errors.go

// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package errors implements functions to manipulate errors.
package errors
// New returns an error that formats as the given text.
func New(text string) error {
return errorString{text}
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}

上面的代碼,并不復雜,參照上面的,咱們進行寫一個自定義錯誤處理。

自定義錯誤處理

咱們定義一個 alarm.go,用于處理告警。

廢話不多說,直接看代碼。

package alarm
import (
"encoding/json"
"fmt"
"ginDemo/common/function"
"path/filepath"
"runtime"
"strings"
)
type errorString struct {
s string
}
type errorInfo struct {
Time string `json:"time"`
Alarm string `json:"alarm"`
Message string `json:"message"`
Filename string `json:"filename"`
Line int `json:"line"`
Funcname string `json:"funcname"`
}
func (e *errorString) Error() string {
return e.s
}
func New (text string) error {
alarm("INFO", text)
return errorString{text}
}
// 發郵件
func Email (text string) error {
alarm("EMAIL", text)
return errorString{text}
}
// 發短信
func Sms (text string) error {
alarm("SMS", text)
return errorString{text}
}
// 發微信
func WeChat (text string) error {
alarm("WX", text)
return errorString{text}
}
// 告警方法
func alarm(level string, str string) {
// 當前時間
currentTime := function.GetTimeStr()
// 定義 文件名、行號、方法名
fileName, line, functionName := "?", 0 , "?"
pc, fileName, line, ok := runtime.Caller(2)
if ok {
functionName = runtime.FuncForPC(pc).Name()
functionName = filepath.Ext(functionName)
functionName = strings.TrimPrefix(functionName, ".")
}
var msg = errorInfo {
Time : currentTime,
Alarm : level,
Message : str,
Filename : fileName,
Line : line,
Funcname : functionName,
}
jsons, errs := json.Marshal(msg)
if errs != nil {
fmt.Println("json marshal error:", errs)
}
errorJsonInfo := string(jsons)
fmt.Println(errorJsonInfo)
if level == "EMAIL" {
// 執行發郵件
} else if level == "SMS" {
// 執行發短信
} else if level == "WX" {
// 執行發微信
} else if level == "INFO" {
// 執行記日志
}
}

看下如何調用:

package v1
import (
"fmt"
"ginDemo/common/alarm"
"ginDemo/entity"
"github.com/gin-gonic/gin"
"net/http"
)
func AddProduct(c *gin.Context) {
// 獲取 Get 參數
name := c.Query("name")
var res = entity.Result{}
str, err := hello(name)
if err != nil {
res.SetCode(entity.CODE_ERROR)
res.SetMessage(err.Error())
c.JSON(http.StatusOK, res)
c.Abort()
return
}
res.SetCode(entity.CODE_SUCCESS)
res.SetMessage(str)
c.JSON(http.StatusOK, res)
}
func hello(name string) (str string, err error) {
if name == "" {
err = alarm.WeChat("name 不能為空")
return
}
str = fmt.Sprintf("hello: %s", name)
return
}

訪問:http://localhost:8080/v1/product/add?name=a

{
"code": 1,
"msg": "hello: a",
"data": null
}

未拋出錯誤,不會輸出信息。

訪問:http://localhost:8080/v1/product/add

{
"code": -1,
"msg": "name 不能為空",
"data": null
}

拋出了錯誤,輸出信息如下:

{"time":"2019-07-23 22:19:17","alarm":"WX","message":"name 不能為空","filename":"絕對路徑/ginDemo/router/v1/product.go","line":33,"funcname":"hello"}

可能這會有同學說:“用上一篇分享的數據綁定和驗證,將傳入的參數進行 binding:"required" 也可以實現呀”。

我只能說:“同學呀,你不理解我的良苦用心,這只是個例子,大家可以在一些復雜的業務邏輯判斷場景中使用自定義錯誤處理”。

到這里,報錯時我們收到了 時間、 錯誤信息、 文件名、 行號、 方法名 了。

調用起來,也比較簡單。

雖然標記了告警方式,還是沒有進行告警通知呀。

我想說,在這里存儲數據到隊列中,再執行異步任務具體去消耗,這塊就不實現了,大家可以去完善。

讀取 文件名、 方法名、 行號 使用的是 runtime.Caller()。

我們還知道,Go 有 panic 和 recover,它們是干什么的呢,接下來咱們就說說。

panic 和 recover

當程序不能繼續運行的時候,才應該使用 panic 拋出錯誤。

當程序發生 panic 后,在 defer(延遲函數) 內部可以調用 recover 進行控制,不過有個前提條件,只有在相同的 Go 協程中才可以。

panic 分兩個,一種是有意拋出的,一種是無意的寫程序馬虎造成的,咱們一個個說。

有意拋出的 panic:

package main
import (
"fmt"
)
func main() {
fmt.Println("-- 1 --")
defer func() {
if r := recover(); r != nil {
fmt.Printf("panic: %s\n", r)
}
fmt.Println("-- 2 --")
}()
panic("i am panic")
}

輸出:

-- 1 --

panic: i am panic

-- 2 --

無意拋出的 panic:

package main
import (
"fmt"
)
func main() {
fmt.Println("-- 1 --")
defer func() {
if r := recover(); r != nil {
fmt.Printf("panic: %s\n", r)
}
fmt.Println("-- 2 --")
}()
var slice = [] int {1, 2, 3, 4, 5}
slice[6] = 6
}

輸出:

-- 1 --

panic: runtime error: index out of range

-- 2 --

上面的兩個我們都通過 recover 捕獲到了,那我們如何在 Gin 框架中使用呢?如果收到 panic 時,也想進行告警怎么實現呢?

既然想實現告警,先在 ararm.go 中定義一個 Panic() 方法,當項目發生 panic 異常時,調用這個方法,這樣就實現告警了。

// Panic 異常
func Panic (text string) error {
alarm("PANIC", text)
return errorString{text}
}

那我們怎么捕獲到呢?

使用中間件進行捕獲,寫一個 recover 中間件。

package recover
import (
"fmt"
"ginDemo/common/alarm"
"github.com/gin-gonic/gin"
)
func Recover() gin.HandlerFunc {
return func(c *gin.Context) {
defer func() {
if r := recover(); r != nil {
alarm.Panic(fmt.Sprintf("%s", r))
}
}()
c.Next()
}
}

路由調用中間件:

r.Use(logger.LoggerToFile(), recover.Recover())
//Use 可以傳遞多個中間件。

驗證下吧,咱們先拋出兩個異常,看看能否捕獲到?

還是修改 product.go 這個文件吧。

有意拋出 panic:

package v1
import (
"fmt"
"ginDemo/entity"
"github.com/gin-gonic/gin"
"net/http"
)
func AddProduct(c *gin.Context) {
// 獲取 Get 參數
name := c.Query("name")
var res = entity.Result{}
str, err := hello(name)
if err != nil {
res.SetCode(entity.CODE_ERROR)
res.SetMessage(err.Error())
c.JSON(http.StatusOK, res)
c.Abort()
return
}
res.SetCode(entity.CODE_SUCCESS)
res.SetMessage(str)
c.JSON(http.StatusOK, res)
}
func hello(name string) (str string, err error) {
if name == "" {
// 有意拋出 panic
panic("i am panic")
return
}
str = fmt.Sprintf("hello: %s", name)
return
}

訪問:http://localhost:8080/v1/product/add

界面是空白的。

拋出了異常,輸出信息如下:

{"time":"2019-07-23 22:42:37","alarm":"PANIC","message":"i am panic","filename":"絕對路徑/ginDemo/middleware/recover/recover.go","line":13,"funcname":"1"}

很顯然,定位的文件名、方法名、行號不是我們想要的。

需要調整 runtime.Caller(2),這個代碼在 alarm.go的alarm 方法中。

將 2 調整成 4 ,看下輸出信息:

{"time":"2019-07-23 22:45:24","alarm":"PANIC","message":"i am panic","filename":"絕對路徑/ginDemo/router/v1/product.go","line":33,"funcname":"hello"}

這就對了。

無意拋出 panic:

// 上面代碼不變
func hello(name string) (str string, err error) {
if name == "" {
// 無意拋出 panic
var slice = [] int {1, 2, 3, 4, 5}
slice[6] = 6
return
}
str = fmt.Sprintf("hello: %s", name)
return
}

訪問:http://localhost:8080/v1/product/add

界面是空白的。

拋出了異常,輸出信息如下:

{"time":"2019-07-23 22:50:06","alarm":"PANIC","message":"runtime error: index out of range","filename":"絕對路徑/runtime/panic.go","line":44,"funcname":"panicindex"}

很顯然,定位的文件名、方法名、行號也不是我們想要的。

將 4 調整成 5 ,看下輸出信息:

{"time":"2019-07-23 22:55:27","alarm":"PANIC","message":"runtime error: index out of range","filename":"絕對路徑/ginDemo/router/v1/product.go","line":34,"funcname":"hello"}

這就對了。

奇怪了,這是為什么?

在這里,有必要說下 runtime.Caller(skip) 了。

skip 指的調用的深度。

為 0 時,打印當前調用文件及行數。

為 1 時,打印上級調用的文件及行數。

依次類推...

在這塊,調用的時候需要注意下,我現在還沒有好的解決方案。

我是將 skip(調用深度),當一個參數傳遞進去。

比如:

// 發微信
func WeChat (text string) error {
alarm("WX", text, 2)
return errorString{text}
}
// Panic 異常
func Panic (text string) error {
alarm("PANIC", text, 5)
return errorString{text}
}

具體的代碼就不貼了。

但是,有意拋出 Panic 和 無意拋出 Panic 的調用深度又不同,怎么辦?

1、盡量將有意拋出的 Panic 改成拋出錯誤的方式。

2、想其他辦法搞定它。

就到這吧。

里面涉及到的代碼,我會更新到 GitHub。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • 解決golang gin框架跨域及注解的問題
  • golang創建文件目錄os.Mkdir,os.MkdirAll的區別說明
  • golang 實現json類型不確定時的轉換
  • Golang 如何判斷數組某個元素是否存在(isset)
  • go 判斷兩個 slice/struct/map 是否相等的實例

標簽:海南 西雙版納 物業服務 儋州 安康 電子產品 遼寧 青海

巨人網絡通訊聲明:本文標題《gin解析json格式的數據出錯的處理方案》,本文關鍵詞  gin,解析,json,格式,的,數據,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《gin解析json格式的數據出錯的處理方案》相關的同類信息!
  • 本頁收集關于gin解析json格式的數據出錯的處理方案的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    国产自产高清不卡| 日韩视频不卡中文| 国产性色一区二区| 欧美色网站导航| 国产激情一区二区三区| 亚洲成人av一区| 欧美高清视频www夜色资源网| 国产在线视视频有精品| 欧美日韩成人综合天天影院| 99久久综合国产精品| 久久综合网色—综合色88| 性做久久久久久免费观看欧美| 欧美草草影院在线视频| av中文字幕一区| 日韩精品成人一区二区三区| 亚洲丝袜美腿综合| 激情综合五月婷婷| 亚洲成av人片一区二区三区| 亚洲欧美日韩中文字幕一区二区三区| 欧美精品一区二区高清在线观看| 欧美在线一二三四区| 性感美女久久精品| 一区二区三区免费网站| 国产亲近乱来精品视频| 欧美高清性hdvideosex| 精品国产不卡一区二区三区| 亚洲精品一卡二卡| 亚洲成人动漫一区| 国产不卡视频在线播放| 91麻豆高清视频| 91精品国产综合久久精品app| 中文字幕免费一区| 三级亚洲高清视频| 久久精品国产99国产| 波多野结衣中文字幕一区二区三区| 欧美日韩电影一区| 欧美精品一二三四| 国产综合色产在线精品| 国产欧美一区二区精品性| 日韩欧美的一区| 日韩欧美一区二区免费| 久久综合九色综合97婷婷| 色偷偷88欧美精品久久久| 色婷婷一区二区三区四区| 丁香天五香天堂综合| 亚洲午夜精品17c| 一区二区三区欧美在线观看| 国产一区二区三区蝌蚪| 欧美精品一二三| 亚洲在线中文字幕| 国产成人在线网站| 欧美大片在线观看| 亚洲日本在线看| 粉嫩av亚洲一区二区图片| 欧美精品久久久久久久久老牛影院| 国产午夜亚洲精品午夜鲁丝片| 免费高清在线一区| 欧美一区二区三区视频免费播放| 亚洲国产一区二区视频| 91麻豆123| 亚洲精品成人少妇| 91年精品国产| 亚洲桃色在线一区| 在线免费不卡视频| 一级中文字幕一区二区| 欧美性色综合网| 亚洲福利一区二区| 欧美久久一二三四区| 五月天一区二区| 日韩免费一区二区| 久久er99热精品一区二区| 日韩精品中文字幕在线不卡尤物| 美女脱光内衣内裤视频久久影院| 欧美一区二区国产| 麻豆一区二区三| 精品免费视频.| 久久99国产精品久久99| 亚洲精品在线三区| 国产一区二区三区视频在线播放| 九九国产精品视频| 欧洲激情一区二区| 国产欧美一区二区三区网站| 麻豆精品精品国产自在97香蕉| 日本韩国一区二区三区视频| 精品精品欲导航| 亚洲品质自拍视频| 国产麻豆精品在线| 日韩欧美国产三级| 欧美高清视频不卡网| 无吗不卡中文字幕| 日韩欧美国产麻豆| 国产麻豆精品在线观看| 亚洲欧美日韩国产综合在线| 91一区一区三区| 一区二区免费在线播放| 91麻豆精品国产91| 久久超碰97中文字幕| 国产亚洲欧美在线| 91国偷自产一区二区三区成为亚洲经典 | 日韩美一区二区三区| 亚洲午夜久久久久中文字幕久| av在线不卡网| 国产欧美精品一区| 国产一区二区h| 欧美一区二区大片| 亚洲另类在线一区| 成人av网站在线| 欧美经典三级视频一区二区三区| 国产成人在线免费| 精品久久久久久综合日本欧美| 午夜一区二区三区视频| 欧美日韩不卡视频| 亚洲精品大片www| 色婷婷av一区二区| 一区二区三区四区不卡视频| eeuss鲁片一区二区三区| 亚洲免费av观看| 欧美午夜免费电影| 综合久久一区二区三区| 国产午夜亚洲精品不卡| 91精品国产欧美一区二区成人| www.亚洲色图.com| 国产成人自拍网| 激情久久久久久久久久久久久久久久 | 91看片淫黄大片一级在线观看| 精品一区二区免费看| 日韩精品福利网| 亚洲午夜久久久久| 一区二区三区日韩精品视频| 国产精品国产三级国产| 久久天堂av综合合色蜜桃网| 日韩三级高清在线| 欧美电影一区二区| 午夜精品影院在线观看| 欧美中文字幕不卡| 国产一区二区三区av电影| 亚洲欧美福利一区二区| 欧美大黄免费观看| 色呦呦网站一区| 国产精品国产三级国产a| 欧美高清www午色夜在线视频| 欧美美女激情18p| 在线成人av影院| 日韩欧美一级精品久久| 日韩一区二区电影| 91精品国产色综合久久久蜜香臀| 日韩一级免费观看| 欧美一级欧美一级在线播放| 日韩视频免费观看高清完整版在线观看 | 欧美日韩国产免费一区二区 | 91久久一区二区| 在线观看精品一区| 欧美无乱码久久久免费午夜一区| 91官网在线观看| 日本久久电影网| 欧美美女喷水视频| 欧美成人女星排名| 精品国产乱码久久久久久免费 | 日韩一区二区三区在线视频| 欧美一区二区三区四区在线观看| 日韩一区二区三区电影在线观看| 日韩一区二区免费在线电影| 欧美videofree性高清杂交| 欧美成人一级视频| 久久久99精品免费观看不卡| 欧美日韩美少妇| 午夜伦理一区二区| 亚洲男女毛片无遮挡| 国产欧美视频一区二区| 欧美一卡二卡在线观看| 欧美日韩视频第一区| 色妹子一区二区| 9i在线看片成人免费| 国产高清在线精品| 美脚の诱脚舐め脚责91| 日本特黄久久久高潮 | 亚洲视频一区二区免费在线观看| 亚洲一区二区三区美女| 麻豆精品久久精品色综合| 成人免费高清在线| 欧美亚洲愉拍一区二区| 国产亚洲综合av| 一区二区日韩电影| 激情亚洲综合在线| 91搞黄在线观看| 国产性天天综合网| 日本女优在线视频一区二区| 99在线精品免费| 日韩精品一区二区三区中文精品| 国产精品欧美一区喷水| 偷拍与自拍一区| 国产91在线|亚洲| 久久久久久久久久久久电影| 精品sm在线观看| 国产欧美精品一区二区色综合朱莉| 国产免费成人在线视频| 国产精品素人一区二区| 亚洲精品免费视频| 日韩在线a电影| 国产美女主播视频一区|