golang使用encoding/json包里面的Marshal将结构体解析成json,结果panic了

问题:使用json.Marshal将结构体解析成json时,程序panic了。
panic的提示为reflect: Field index out of range
使用的golang的版本是1.15,服务运行的服务器版本是CentOS Linux release 7.9.2009 (Core)

具体出错信息:

2021/04/22 18:19:21 http: panic serving 127.0.0.1:30418: reflect: Field index out of range
goroutine 15849 [running]:
net/http.(*conn).serve.func1(0xc00052a140)
    /usr/local/go/src/net/http/server.go:1801 +0x147
panic(0x872fe0, 0x9a7690)
    /usr/local/go/src/runtime/panic.go:975 +0x47a
encoding/json.(*encodeState).marshal.func1(0xc000329880)
    /usr/local/go/src/encoding/json/encode.go:326 +0x85
panic(0x872fe0, 0x9a7690)
    /usr/local/go/src/runtime/panic.go:969 +0x1b9
reflect.Value.Field(0x90a360, 0xc000112c00, 0x199, 0xffffffff, 0x454cc7, 0x0, 0xc000329538)
    **/usr/local/go/src/reflect/value.go:854 +0xd9**
encoding/json.structEncoder.encode(0xc0002d6900, 0xf, 0x10, 0xc000290c60, 0xc0001d0200, 0x90a360, 0xc000112c00, 0x199, 0x100)
    /usr/local/go/src/encoding/json/encode.go:745 +0x85
encoding/json.arrayEncoder.encode(0xc000290cc0, 0xc0001d0200, 0x86d800, 0xc0005ec348, 0x97, 0xc000110100)
    /usr/local/go/src/encoding/json/encode.go:886 +0xd6
encoding/json.sliceEncoder.encode(0xc000170d80, 0xc0001d0200, 0x86d800, 0xc0005ec348, 0x97, 0x100)
    /usr/local/go/src/encoding/json/encode.go:860 +0x8f
encoding/json.structEncoder.encode(0xc0000ebb00, 0x5, 0x8, 0xc000290cf0, 0xc0001d0200, 0x8dee60, 0xc0005ec340, 0x99, 0x8d0100)
    /usr/local/go/src/encoding/json/encode.go:759 +0x2ab
encoding/json.(*encodeState).reflectValue(0xc0001d0200, 0x8dee60, 0xc0005ec340, 0x99, 0xc000320100)
    /usr/local/go/src/encoding/json/encode.go:358 +0x82
encoding/json.(*encodeState).marshal(0xc0001d0200, 0x8dee60, 0xc0005ec340, 0x100, 0x0, 0x0)
    /usr/local/go/src/encoding/json/encode.go:330 +0xf4
encoding/json.Marshal(0x8dee60, 0xc0005ec340, 0x8dee60, 0xc0005ec340, 0x0, 0x1, 0xa)
    /usr/local/go/src/encoding/json/encode.go:161 +0x52
schedule.TaskExecResultHandler(0x9b8ec0, 0xc0002940e0, 0xc000374200)
    **/home/lrf/gitlab/vrv-job/job-engine/schedule/web.go:258** +0x64e
net/http.HandlerFunc.ServeHTTP(0x945580, 0x9b8ec0, 0xc0002940e0, 0xc000374200)
    /usr/local/go/src/net/http/server.go:2042 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc0001283c0, 0x9b8ec0, 0xc0002940e0, 0xc000374000)
    /home/lrf/golang/pkg/mod/github.com/gorilla/mux@v1.8.0/mux.go:210 +0xd3
net/http.serverHandler.ServeHTTP(0xc000294000, 0x9b8ec0, 0xc0002940e0, 0xc000374000)
    /usr/local/go/src/net/http/server.go:2843 +0xa3
net/http.(*conn).serve(0xc00052a140, 0x9b9d80, 0xc0005ec000)
    /usr/local/go/src/net/http/server.go:1925 +0x8ad
created by net/http.(*Server).Serve
    /usr/local/go/src/net/http/server.go:2969 +0x36c

出错处代码:

type QueryTaskExecResult struct {
    Code       int                   `json:"code"`
    Result     []taskdb.TaskExecutor `json:"result"`
    TotalPage  int64                 `json:"totalPage"`
    TotalCount int64                 `json:"totalCount"`
    ErrMsg     string                `json:"errMsg"`
}
var result QueryTaskExecResult
...
by, err := json.Marshal(result) //出错行

panic处代码

 846 // Field returns the i'th field of the struct v.
 847 // It panics if v's Kind is not Struct or i is out of range.
 848 func (v Value) Field(i int) Value {
 849     if v.kind() != Struct {
 850         panic(&ValueError{"reflect.Value.Field", v.kind()})
 851     }
 852     tt := (*structType)(unsafe.Pointer(v.typ))
 853     if uint(i) >= uint(len(tt.fields)) {
 854         panic("reflect: Field index out of range")
 855     }
 856     field := &tt.fields[i]
 857     typ := field.typ
         ...

出错误时的操作
服务启了个http服务,然后一直使用postman进行查询操作,有几率触发该panic。
并且,调用json.Unmarshal解析入参时也有几率报reflect: Field index out of range
出现的频率很高,几乎是必现。
请教各位大神,这种挂在官方库中的地方,该如何排查?

阅读 6.6k
2 个回答

我自己尝试复现没成功,是否能提供完整的可复现问题的代码?或者至少把taskdb.TaskExecutor是什么以及是怎么生成的说明下。
如果不能,
1.你可以在structEncoder.encode加日志调试。
2.应该是QueryTaskExecResult.Result导致的,仔细看看这个结构是不是并发不安全什么的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏