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

主頁(yè) > 知識(shí)庫(kù) > gin解析json格式的數(shù)據(jù)出錯(cuò)的處理方案

gin解析json格式的數(shù)據(jù)出錯(cuò)的處理方案

熱門標(biāo)簽:湛江crm外呼系統(tǒng)排名 重慶慶云企業(yè)400電話到哪申請(qǐng) 不封卡外呼系統(tǒng) 地圖標(biāo)注免費(fèi)定制店 上海極信防封電銷卡價(jià)格 鄭州智能語音電銷機(jī)器人價(jià)格 宿遷便宜外呼系統(tǒng)代理商 仙桃400電話辦理 寧波語音外呼系統(tǒng)公司

寫的接口給測(cè)試測(cè)試,現(xiàn)在還沒有頁(yè)面,直接測(cè)試接口。使用

c.BindJSON(req)

總是報(bào)錯(cuò),大致錯(cuò)誤信息如下:

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

這是由于我的接口要求將參數(shù)按照json格式傳遞到后臺(tái),結(jié)果測(cè)試同事使用了form-data格式,所以才會(huì)有上面這個(gè)錯(cuò)誤。

=============補(bǔ)充2018-11-09 18:20:00=============

剛剛又出現(xiàn)了這個(gè)EOF的問題,前端確定已經(jīng)按照json格式傳參,但是還是有這個(gè)問題。

通過wireshark抓包發(fā)現(xiàn),前端給的Content-Length為0,說明沒有將參數(shù)傳入后臺(tái)。

后來前端核查代碼發(fā)現(xiàn),確實(shí)是沒有將參數(shù)傳入,只是定義了

補(bǔ)充:gin json 獲取_Gin框架系列 自定義錯(cuò)誤處理

概述

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

開始今天的文章,為什么要自定義錯(cuò)誤處理?默認(rèn)的錯(cuò)誤處理方式是什么?

那好,咱們就先說下默認(rèn)的錯(cuò)誤處理。

默認(rèn)的錯(cuò)誤處理是 errors.New("錯(cuò)誤信息"),這個(gè)信息通過 error 類型的返回值進(jìn)行返回。

舉個(gè)簡(jiǎn)單的例子:

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

當(dāng)調(diào)用這個(gè)方法時(shí):

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

這就是默認(rèn)的錯(cuò)誤處理,下面還會(huì)用這個(gè)例子進(jìn)行說。

這個(gè)默認(rèn)的錯(cuò)誤處理,只是得到了一個(gè)錯(cuò)誤信息的字符串。

然而...

我還想得到發(fā)生錯(cuò)誤時(shí)的 時(shí)間、 文件名、 方法名、 行號(hào) 等信息。

我還想得到錯(cuò)誤時(shí)進(jìn)行告警,比如 短信告警、 郵件告警、 微信告警 等。

我還想調(diào)用的時(shí)候,不那么復(fù)雜,就和默認(rèn)錯(cuò)誤處理類似,比如:

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

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

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

還要保證,我們業(yè)務(wù)邏輯中,獲取錯(cuò)誤的時(shí)候,只獲取錯(cuò)誤信息即可。

上面這些想出來的,就是今天要實(shí)現(xiàn)的,自定義錯(cuò)誤處理,我們就實(shí)現(xiàn)之前,先說下 Go 的錯(cuò)誤處理。

錯(cuò)誤處理

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

當(dāng) name = "" 時(shí),輸出:

param:

name 不能為空

建議每個(gè)函數(shù)都要有錯(cuò)誤處理,error 應(yīng)該為最后一個(gè)返回值。

咱們一起看下官方 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
}

上面的代碼,并不復(fù)雜,參照上面的,咱們進(jìn)行寫一個(gè)自定義錯(cuò)誤處理。

自定義錯(cuò)誤處理

咱們定義一個(gè) 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}
}
// 發(fā)郵件
func Email (text string) error {
alarm("EMAIL", text)
return errorString{text}
}
// 發(fā)短信
func Sms (text string) error {
alarm("SMS", text)
return errorString{text}
}
// 發(fā)微信
func WeChat (text string) error {
alarm("WX", text)
return errorString{text}
}
// 告警方法
func alarm(level string, str string) {
// 當(dāng)前時(shí)間
currentTime := function.GetTimeStr()
// 定義 文件名、行號(hào)、方法名
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" {
// 執(zhí)行發(fā)郵件
} else if level == "SMS" {
// 執(zhí)行發(fā)短信
} else if level == "WX" {
// 執(zhí)行發(fā)微信
} else if level == "INFO" {
// 執(zhí)行記日志
}
}

看下如何調(diào)用:

package v1
import (
"fmt"
"ginDemo/common/alarm"
"ginDemo/entity"
"github.com/gin-gonic/gin"
"net/http"
)
func AddProduct(c *gin.Context) {
// 獲取 Get 參數(shù)
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
}

未拋出錯(cuò)誤,不會(huì)輸出信息。

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

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

拋出了錯(cuò)誤,輸出信息如下:

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

可能這會(huì)有同學(xué)說:“用上一篇分享的數(shù)據(jù)綁定和驗(yàn)證,將傳入的參數(shù)進(jìn)行 binding:"required" 也可以實(shí)現(xiàn)呀”。

我只能說:“同學(xué)呀,你不理解我的良苦用心,這只是個(gè)例子,大家可以在一些復(fù)雜的業(yè)務(wù)邏輯判斷場(chǎng)景中使用自定義錯(cuò)誤處理”。

到這里,報(bào)錯(cuò)時(shí)我們收到了 時(shí)間、 錯(cuò)誤信息、 文件名、 行號(hào)、 方法名 了。

調(diào)用起來,也比較簡(jiǎn)單。

雖然標(biāo)記了告警方式,還是沒有進(jìn)行告警通知呀。

我想說,在這里存儲(chǔ)數(shù)據(jù)到隊(duì)列中,再執(zhí)行異步任務(wù)具體去消耗,這塊就不實(shí)現(xiàn)了,大家可以去完善。

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

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

panic 和 recover

當(dāng)程序不能繼續(xù)運(yùn)行的時(shí)候,才應(yīng)該使用 panic 拋出錯(cuò)誤。

當(dāng)程序發(fā)生 panic 后,在 defer(延遲函數(shù)) 內(nèi)部可以調(diào)用 recover 進(jìn)行控制,不過有個(gè)前提條件,只有在相同的 Go 協(xié)程中才可以。

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

有意拋出的 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 --

上面的兩個(gè)我們都通過 recover 捕獲到了,那我們?nèi)绾卧?Gin 框架中使用呢?如果收到 panic 時(shí),也想進(jìn)行告警怎么實(shí)現(xiàn)呢?

既然想實(shí)現(xiàn)告警,先在 ararm.go 中定義一個(gè) Panic() 方法,當(dāng)項(xiàng)目發(fā)生 panic 異常時(shí),調(diào)用這個(gè)方法,這樣就實(shí)現(xiàn)告警了。

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

那我們?cè)趺床东@到呢?

使用中間件進(jìn)行捕獲,寫一個(gè) 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()
}
}

路由調(diào)用中間件:

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

驗(yàn)證下吧,咱們先拋出兩個(gè)異常,看看能否捕獲到?

還是修改 product.go 這個(gè)文件吧。

有意拋出 panic:

package v1
import (
"fmt"
"ginDemo/entity"
"github.com/gin-gonic/gin"
"net/http"
)
func AddProduct(c *gin.Context) {
// 獲取 Get 參數(shù)
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":"絕對(duì)路徑/ginDemo/middleware/recover/recover.go","line":13,"funcname":"1"}

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

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

將 2 調(diào)整成 4 ,看下輸出信息:

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

這就對(duì)了。

無意拋出 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":"絕對(duì)路徑/runtime/panic.go","line":44,"funcname":"panicindex"}

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

將 4 調(diào)整成 5 ,看下輸出信息:

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

這就對(duì)了。

奇怪了,這是為什么?

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

skip 指的調(diào)用的深度。

為 0 時(shí),打印當(dāng)前調(diào)用文件及行數(shù)。

為 1 時(shí),打印上級(jí)調(diào)用的文件及行數(shù)。

依次類推...

在這塊,調(diào)用的時(shí)候需要注意下,我現(xiàn)在還沒有好的解決方案。

我是將 skip(調(diào)用深度),當(dāng)一個(gè)參數(shù)傳遞進(jìn)去。

比如:

// 發(fā)微信
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 的調(diào)用深度又不同,怎么辦?

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

2、想其他辦法搞定它。

就到這吧。

里面涉及到的代碼,我會(huì)更新到 GitHub。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

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

標(biāo)簽:海南 西雙版納 物業(yè)服務(wù) 儋州 安康 電子產(chǎn)品 遼寧 青海

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《gin解析json格式的數(shù)據(jù)出錯(cuò)的處理方案》,本文關(guān)鍵詞  gin,解析,json,格式,的,數(shù)據(jù),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《gin解析json格式的數(shù)據(jù)出錯(cuò)的處理方案》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于gin解析json格式的數(shù)據(jù)出錯(cuò)的處理方案的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    久久精品理论片| 欧美大黄免费观看| 99久久精品国产一区| 色综合色狠狠天天综合色| 北条麻妃一区二区三区| 欧美在线一区二区| 欧美不卡一区二区三区四区| 中文字幕不卡三区| 亚洲bt欧美bt精品| 北条麻妃国产九九精品视频| 欧美视频中文一区二区三区在线观看| 欧美日韩国产首页| 国产欧美精品一区二区色综合| 亚洲免费观看高清完整版在线观看| 一区二区日韩电影| 国产91高潮流白浆在线麻豆| 欧美二区乱c少妇| 中文成人综合网| 精品一区二区三区不卡| 在线成人小视频| 亚洲人一二三区| av亚洲精华国产精华| 26uuu国产日韩综合| 日韩精品亚洲专区| 欧美一区二区三级| 亚洲一区在线观看视频| 亚洲高清一区二区三区| 亚洲一区二区精品视频| 国产一区二区按摩在线观看| 26uuu另类欧美| 国产麻豆视频一区二区| 亚洲国产成人一区二区三区| 天使萌一区二区三区免费观看| 91蜜桃在线观看| 一区二区三区高清| 日韩欧美一区在线| 国产.精品.日韩.另类.中文.在线.播放| 精品国产免费人成电影在线观看四季 | 91丨porny丨最新| 一区二区三区91| 精品久久人人做人人爰| 91偷拍与自偷拍精品| 亚洲精品国产精品乱码不99| 制服丝袜成人动漫| 成人国产亚洲欧美成人综合网| 自拍视频在线观看一区二区| 欧美日韩免费电影| 国产精品自拍毛片| 日韩黄色在线观看| 中文字幕中文乱码欧美一区二区| 欧美日韩国产一区二区三区地区| 精品一区二区三区免费播放| 亚洲一区二区三区四区在线免费观看 | 欧美大黄免费观看| 欧美在线免费观看亚洲| 国产精品自拍在线| 精品一区二区三区在线观看国产| 中文字幕在线不卡| 国产精品丝袜在线| 精品国产免费久久| 精品三级在线看| 5566中文字幕一区二区电影 | 久久99久久久久| 日韩中文字幕一区二区三区| 国产精品婷婷午夜在线观看| 欧美精品一区二区久久久| 日韩精品一区二区三区在线观看 | 国产资源在线一区| 国产在线视视频有精品| 久久国产精品第一页| 国产乱人伦偷精品视频不卡 | 亚洲激情自拍偷拍| 亚洲另类一区二区| 日本aⅴ精品一区二区三区 | 91黄色免费版| 粉嫩久久99精品久久久久久夜 | 色系网站成人免费| 91在线免费视频观看| 欧美丝袜丝交足nylons| 欧美一区二区二区| 91精品午夜视频| 日本一区二区三区四区在线视频| 日本一区二区三区dvd视频在线| 欧美精品一区二区高清在线观看| 91精品国产综合久久婷婷香蕉| 91精品国模一区二区三区| 欧美日韩一区小说| 日韩精品一区在线| 精品成人一区二区三区四区| 精品国产欧美一区二区| 久久精品亚洲麻豆av一区二区 | 日韩一区二区三区在线| 一区在线观看视频| 精品一区二区三区免费观看| 91免费观看视频| 亚洲国产成人午夜在线一区| 久久激五月天综合精品| 欧美日韩久久不卡| 亚洲精品国产无套在线观| 国产乱码精品一品二品| 91精品婷婷国产综合久久竹菊| 亚洲精品乱码久久久久久久久 | 一区二区三区国产豹纹内裤在线| 国产乱人伦偷精品视频免下载| 欧美日韩国产综合一区二区三区| 国产精品久久久久久久久图文区| 国产欧美一区二区在线观看| 欧美三级视频在线| 亚洲日本免费电影| 成人一区二区在线观看| 国产精品理论在线观看| heyzo一本久久综合| 亚洲欧美日韩国产综合在线| 一本色道久久综合亚洲精品按摩| 自拍偷拍国产精品| av一区二区三区| 日本伊人色综合网| 久久久不卡网国产精品二区| 成人免费视频免费观看| 一级日本不卡的影视| 欧美亚州韩日在线看免费版国语版| 亚洲综合免费观看高清完整版在线| 欧美三级中文字| 精品一区二区精品| 亚洲人成精品久久久久| 欧美亚洲国产一区二区三区 | 亚洲男人的天堂在线aⅴ视频| 成人av小说网| 亚洲精品国产第一综合99久久 | 国产一区不卡精品| 综合色中文字幕| 精品久久久网站| 色先锋资源久久综合| 国产精品99久久久| 一本色道久久综合精品竹菊| 日本在线不卡一区| 亚洲国产综合91精品麻豆| 欧美tk—视频vk| 91精品中文字幕一区二区三区| 高清不卡一二三区| 蜜臀精品久久久久久蜜臀| 亚洲美女区一区| 亚洲精品在线一区二区| 欧美精品乱码久久久久久按摩| 国产精品一区二区三区99| 一区二区三区四区在线播放| 国产三级一区二区| 久久免费视频一区| 欧美激情中文不卡| 国产精品三级av| 亚洲国产精品v| 自拍偷拍亚洲激情| 国产精品色一区二区三区| 日本一区二区三区dvd视频在线| 欧美成人aa大片| 欧美激情在线一区二区三区| 中文字幕av一区 二区| 中文字幕va一区二区三区| 欧美极品xxx| 亚洲自拍偷拍图区| 亚洲一区二区四区蜜桃| 日本va欧美va欧美va精品| 老司机免费视频一区二区 | 日韩欧美国产高清| 久久久无码精品亚洲日韩按摩| 国产亚洲午夜高清国产拍精品| 国产精品成人一区二区三区夜夜夜| 中文字幕va一区二区三区| 亚洲一区中文日韩| 成人激情动漫在线观看| 日韩欧美中文一区二区| 亚洲一区国产视频| 99国产精品国产精品久久| 久久久影院官网| 亚洲最大成人综合| 在线视频国产一区| 亚洲精品久久嫩草网站秘色| 91网站视频在线观看| 国产精品大尺度| av亚洲产国偷v产偷v自拍| 久久只精品国产| 狠狠狠色丁香婷婷综合激情| 91亚洲资源网| 中文字幕日韩一区二区| 成人av在线看| 亚洲男人天堂av| 欧美日韩精品一区二区三区蜜桃| 亚洲婷婷综合久久一本伊一区| 国产精品99久久久久久久女警| 国产精品污污网站在线观看| 色中色一区二区| 天堂成人国产精品一区| 亚洲精品一线二线三线| 高清在线成人网| 香蕉久久一区二区不卡无毒影院| 欧美一区二区三区白人| 91亚洲永久精品| 免费国产亚洲视频| 亚洲男人电影天堂| 久久中文娱乐网|