2023年11月29日发(作者:)

gin解析json格式的数据出错的处理⽅案

写的接⼝给测试测试,现在还没有页⾯,直接测试接⼝。使⽤

ON(&req)

总是报错,⼤致错误信息如下:

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

这是由于我的接⼝要求将参数按照json格式传递到后台,结果测试同事使⽤了form-data格式,所以才会有上⾯这个错误。

=============补充2018-11-09 182000=============

刚刚⼜出现了这个EOF的问题,前端确定已经按照json格式传参,但是还是有这个问题。

通过wireshark抓包发现,前端给的Content-Length0,说明没有将参数传⼊后台。

后来前端核查代码发现,确实是没有将参数传⼊,只是定义了

补充:gin json 获取_Gin框架系列 ⾃定义错误处理

概述

开始今天的⽂章,为什么要⾃定义错误处理?默认的错误处理⽅式是什么?

那好,咱们就先说下默认的错误处理。

默认的错误处理是 ("错误信息"),这个信息通过 error 类型的返回值进⾏返回。

举个简单的例⼦:

func hello(name string) (str string, err error) {

if name == "" {

err = ("name 不能为空")

return

}

str = f("hello: %s", name)

return

}

当调⽤这个⽅法时:

var name = ""

str, err := hello(name)

if err != nil {

n(())

return

}

这就是默认的错误处理,下⾯还会⽤这个例⼦进⾏说。

这个默认的错误处理,只是得到了⼀个错误信息的字符串。

然⽽...

我还想得到发⽣错误时的 时间、 ⽂件名、 ⽅法名、 ⾏号 等信息。

我还想得到错误时进⾏告警,⽐如 短信告警、 邮件告警、 微信告警 等。

我还想调⽤的时候,不那么复杂,就和默认错误处理类似,⽐如:

("错误信息")

return

这样,我们就得到了我们想要的信息( 时间、 ⽂件名、 ⽅法名、 ⾏号),并通过 微信 的⽅式进⾏告警通知我们。

同理, ("错误信息") ("错误信息") 我们得到的信息是⼀样的,只是告警⽅式不同⽽已。

还要保证,我们业务逻辑中,获取错误的时候,只获取错误信息即可。

上⾯这些想出来的,就是今天要实现的,⾃定义错误处理,我们就实现之前,先说下 Go 的错误处理。

错误处理

package main

import (

"errors"

"fmt"

)

func hello(name string) (str string, err error) {

if name == "" {

err = ("name 不能为空")

return

}

str = f("hello: %s", name)

return

}

"fmt"

"ginDemo/common/function"

"path/filepath"

"runtime"

看下如何调⽤:

package v1

import (

"fmt"

"ginDemo/common/alarm"

"ginDemo/entity"

"/gin-gonic/gin"

"net/http"

)

func AddProduct(c *t) {

// 获取 Get 参数

name := ("name")

var res = {}

str, err := hello(name)

if err != nil {

e(_ERROR)

sage(())

(OK, res)

()

return

}

e(_SUCCESS)

sage(str)

(OK, res)

}

func hello(name string) (str string, err error) {

if name == "" {

err = ("name 不能为空")

return

}

str = f("hello: %s", name)

return

}

{

"code": 1,

"msg": "hello: a",

"data": null

}

未抛出错误,不会输出信息。

{

"code": -1,

"msg": "name 不能为空",

"data": null

}

抛出了错误,输出信息如下:

{"time":"2019-07-23 22:19:17","alarm":"WX","message":"name 不能为空","filename":"绝对路

/ginDemo/router/v1/","line":33,"funcname":"hello"}

可能这会有同学说:⽤上⼀篇分享的数据绑定和验证,将传⼊的参数进⾏ binding:"required" 也可以实现呀

我只能说:同学呀,你不理解我的良苦⽤⼼,这只是个例⼦,⼤家可以在⼀些复杂的业务逻辑判断场景中使⽤⾃定义错误处

到这⾥,报错时我们收到了 时间、 错误信息、 ⽂件名、 ⾏号、 ⽅法名 了。

调⽤起来,也⽐较简单。

当程序不能继续运⾏的时候,才应该使⽤ panic 抛出错误。

当程序发⽣ panic 后,在 defer(延迟函数) 内部可以调⽤ recover 进⾏控制,不过有个前提条件,只有在相同的 Go 协程中才可

以。

panic 分两个,⼀种是有意抛出的,⼀种是⽆意的写程序马虎造成的,咱们⼀个个说。

有意抛出的 panic

package main

import (

"fmt"

)

func main() {

n("-- 1 --")

defer func() {

if r := recover(); r != nil {

("panic: %sn", r)

}

n("-- 2 --")

}()

panic("i am panic")

}

输出:

-- 1 --

panic: i am panic

-- 2 --

⽆意抛出的 panic

package main

import (

"fmt"

)

func main() {

n("-- 1 --")

import (

"fmt"

"ginDemo/common/alarm"

"/gin-gonic/gin"

)

func Recover() rFunc {

return func(c *t) {

defer func() {

if r := recover(); r != nil {

(f("%s", r))

}

}()

()

}

}

路由调⽤中间件:

(ToFile(), r())

//Use 可以传递多个中间件。

验证下吧,咱们先抛出两个异常,看看能否捕获到?

还是修改 这个⽂件吧。

/ginDemo/router/v1/","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 = f("hello: %s", name)

return

}

界⾯是空⽩的。

抛出了异常,输出信息如下:

{"time":"2019-07-23 22:50:06","alarm":"PANIC","message":"runtime error: index out of range","filename":"绝对路

/runtime/","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/","line":34,"funcname":"hello"}

这就对了。

奇怪了,这是为什么?

在这⾥,有必要说下 (skip) 了。

skip 指的调⽤的深度。

0 时,打印当前调⽤⽂件及⾏数。

⾥⾯涉及到的代码,我会更新到 GitHub

以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。如有错误或未考虑完全的地⽅,望不吝赐教。