dongou3158 2013-05-19 12:19
浏览 212
已采纳

使用go发送JSON

I'm trying to send a JSON message with Go. This is the server code:

func (network *Network) Join(
    w http.ResponseWriter,
    r *http.Request) {
    //the request is not interesting
    //the response will be a message with just the clientId value set
    log.Println("client wants to join")
    message := Message{-1, -1, -1, ClientId(len(network.Clients)), -1, -1}
    var buffer bytes.Buffer
    enc := json.NewEncoder(&buffer)

    err := enc.Encode(message)
    if err != nil {
        fmt.Println("error encoding the response to a join request")
        log.Fatal(err)
    }

    fmt.Printf("the json: %s
", buffer.Bytes())
    fmt.Fprint(w, buffer.Bytes())
}

Network is a custom struct. In the main function, I'm creating a network object and registering it's methods as callbacks to http.HandleFunc(...)

func main() {
    runtime.GOMAXPROCS(2)
    var network = new(Network)
    var clients = make([]Client, 0, 10)
    network.Clients = clients

    log.Println("starting the server")
    http.HandleFunc("/request", network.Request)
    http.HandleFunc("/update", network.GetNews)
    http.HandleFunc("/join", network.Join)
    log.Fatal(http.ListenAndServe("localhost:5000", nil))
}

Message is a struct, too. It has six fields all of a type alias for int. When a client sends an http GET request to the url "localhost:5000/join", this should happen

  • The method Join on the network object is called
  • A new Message object with an Id for the client is created
  • This Message is encoded as JSON
  • To check if the encoding is correct, the encoded message is printed on the cmd
  • The message is written to the ResponseWriter

The client is rather simple. It has the exact same code for the Message struct. In the main function it just sends a GET request to "localhost:5000/join" and tries to decode the response. Here's the code

func main() {

    // try to join
    var clientId ClientId
    start := time.Now()
    var message Message
    resp, err := http.Get("http://localhost:5000/join")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(resp.Status)
    dec := json.NewDecoder(resp.Body)
    err = dec.Decode(&message)
    if err != nil {
        fmt.Println("error decoding the response to the join request")
        log.Fatal(err)
    }

    fmt.Println(message)
    duration := time.Since(start)
    fmt.Println("connected after: ", duration)
    fmt.Println("with clientId", message.ClientId)
}

I've started the server, waited a few seconds and then ran the client. This is the result

  • The server prints "client wants to join"
  • The server prints "the json: {"What":-1,"Tag":-1,"Id":-1,"ClientId":0,"X":-1,"Y":-1}"
  • The client prints "200 OK"
  • The client crashes "error decoding the response to the join request"
  • The error is "invalid character "3" after array element"

This error message really confused me. After all, nowhere in my json, there's the number 3. So I imported io/ioutil on the client and just printed the response with this code

b, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("the json: %s
", b)

Please note that the print statement is the same as on the server. I expected to see my encoded JSON. Instead I got this

  • "200 OK"
  • "the json: [123 34 87 104 97 116 ....]" the list went on for a long time

I'm new to go and don't know if i did this correctly. But it seems as if the above code just printed the slice of bytes. Strange, on the server the output was converted to a string.

My guess is that somehow I'm reading the wrong data or that the message was corrupted on the way between server and client. But honestly these are just wild guesses.

  • 写回答

2条回答 默认 最新

  • duanpai6581 2013-05-19 15:08
    关注

    In your server, instead of

    fmt.Fprint(w, buffer.Bytes())
    

    you need to use:

    w.Write(buffer.Bytes())
    

    The fmt package will format the Bytes() into a human-readable slice with the bytes represented as integers, like so:

    [123 34 87 104 97 116 ... etc
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 Cesm如何关闭不用的模块呢
  • ¥15 vue2两层数据导出为excle
  • ¥15 有人能帮我做一下这个项目吗
  • ¥15 网络上传速率比下载速率高
  • ¥15 (标签-游戏|关键词-网页游戏)
  • ¥15 这个咋搞🥹可能需要手把手教
  • ¥15 RFID标签芯片ROCKY100配置成SPI主机问题
  • ¥15 接口和关键字的问题,多选
  • ¥15 yolov5s模型下载就卡住,没有运行结果
  • ¥20 androidstudio工具问题