2023年11月29日发(作者:)
gin解析json格式的数据出错的处理⽅案
写的接⼝给测试测试,现在还没有页⾯,直接测试接⼝。使⽤
ON(&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框架系列 ⾃定义错误处理
概述
开始今天的⽂章,为什么要⾃定义错误处理?默认的错误处理⽅式是什么?
那好,咱们就先说下默认的错误处理。
默认的错误处理是 ("错误信息"),这个信息通过 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。
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。如有错误或未考虑完全的地⽅,望不吝赐教。


发布评论