golang: json.Unmarshal() 返回 “无效的内存地址或空指针解引用”。

huangapple go评论115阅读模式
英文:

golang: json.Unmarshal() returns "invalid memory address or nil pointer dereference"

问题

我从一个 WebSocket 收到了一个 JSON 消息,JSON 字符串接收正常。然后我调用了 json.Unmarshal 函数,但出现了运行时 panic。我查看了其他示例,但这似乎是另外的问题。以下是代码:

  1. func translateMessages(s socket) {
  2. message := make([]byte, 4096)
  3. for {
  4. fmt.Printf("Waiting for a message ... \n")
  5. if n, err := s.Read(message); err == nil {
  6. command := map[string]interface{}{}
  7. fmt.Printf("Received message: %v (%d Bytes)\n", string(message[:n]), n)
  8. err := json.Unmarshal(message[:n], &command)
  9. fmt.Printf("Received command: %v (Error: %s)\n", command, err.Error())
  10. }
  11. }
  12. }

以下是输出结果:

  1. Waiting for a message ...
  2. Received message: {"gruss":"Hello World!"} (24 Bytes)
  3. panic: runtime error: invalid memory address or nil pointer dereference
  4. [signal 0xb code=0x1 addr=0x20 pc=0x401938]
  5. goroutine 25 [running]:
  6. runtime.panic(0x6f4860, 0x8ec333)

有什么提示可以解决这个问题吗?

英文:

I get a json message from a websocket an the json string is received ok. Then I call json.Unmarshal an get a runtime panic. I looked through the other examples, but this seems to be something else. Here is the code:

  1. func translateMessages(s socket) {
  2. message := make([]byte,4096)
  3. for {
  4. fmt.Printf("Waiting for a message ... \n")
  5. if n, err := s.Read(message); err == nil {
  6. command := map[string]interface{}{}
  7. fmt.Printf("Received message: %v (%d Bytes)\n", string(message[:n]), n)
  8. err := json.Unmarshal(message[:n],&command)
  9. fmt.Printf("Received command: %v (Error: %s)\n", command, err.Error())
  10. }
  11. }
  12. }

And this is the output:

  1. Waiting for a message ...
  2. Received message: {"gruss":"Hello World!"} (24 Bytes)
  3. panic: runtime error: invalid memory address or nil pointer dereference
  4. [signal 0xb code=0x1 addr=0x20 pc=0x401938]
  5. goroutine 25 [running]:
  6. runtime.panic(0x6f4860, 0x8ec333)

Any hint what that could be?

答案1

得分: 2

如果在解码JSON时没有错误,这行代码将会引发panic:

  1. fmt.Printf("Received command: %v (Error: %s)\n", command, err.Error())

如果err == nil,那么err.Error()将会引发空指针解引用的panic。将该行代码改为:

  1. fmt.Printf("Received command: %v (Error: %v)\n", command, err)

如果你正在读取一个socket,那么不能保证s.Read()会读取到一个完整的JSON值。编写这个函数的更好方式是:

  1. func translateMessages(s socket) {
  2. d := json.NewDecoder(s)
  3. for {
  4. fmt.Printf("Waiting for a message ... \n")
  5. var command map[string]interface{}
  6. err := d.Decode(&command)
  7. fmt.Printf("Received command: %v (Error: %v)\n", command, err)
  8. if err != nil {
  9. return
  10. }
  11. }
  12. }

如果你正在使用websockets,那么你应该使用gorilla/websocket包和ReadJSON来解码JSON值。

英文:

This line will panic if there's no error decoding the JSON:

  1. fmt.Printf("Received command: %v (Error: %s)\n", command, err.Error())

If err == nil, then err.Error() panics with nil pointer derference. Change the line to:

  1. fmt.Printf("Received command: %v (Error: %v)\n", command, err)

If you are reading a socket, then there's no guarantee that s.Read() will read a complete JSON value. A better way to write this function is:

  1. func translateMessages(s socket) {
  2. d := json.NewDecoder(s)
  3. for {
  4. fmt.Printf("Waiting for a message ... \n")
  5. var command map[string]interface{}
  6. err := d.Decode(&command)
  7. fmt.Printf("Received command: %v (Error: %v)\n", command, err)
  8. if err != nil {
  9. return
  10. }
  11. }
  12. }

If you are working with websockets, then you should use the gorilla/webscoket package and ReadJSON to decode JSON values.

huangapple
  • 本文由 发表于 2015年1月19日 00:36:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/28012123.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定