dsce23640 2018-12-13 00:03
浏览 57
已采纳

Golang中特定于平台的反序列化?

I am hitting a REST API and getting some data back. I came across an interesting behaviour yesterday. I haven't understood the exact reasoning behind the it yet. Which is what I'm trying to seek here. For a payload that looks like -

{
    "id": 2091967,
    "first_name": "",
    "last_name": "",
    "email": "",
    "telephone": "",
    "timezone": "",
    "weekly_capacity": "",
    "has_access_to_all_future_projects": false,
    "is_contractor": false,
    "is_admin": false,
    "is_project_manager": false,
    "can_see_rates": false,
    "can_create_projects": false,
    "can_create_invoices": false,
    "is_active": false,
    "created_at": "2018-04-16T00:48:30Z",
    "updated_at": "2018-11-07T22:47:43Z",
    "default_hourly_rate": null,
    "cost_rate": null,
    "roles": [
        "blah"
    ],
    "avatar_url": ""
}

I used a function like below to get the email -

func GetUserEmail(userID int) string {
    resp := getFromSomething("https://something/users/" + strconv.Itoa(userID))
    var result map[string]string

    json.NewDecoder(resp.Body).Decode(&result)
    log.Printf("userEmail: %s", result["email"])
    return result["email"]
}

The code worked perfectly on my mac where I was building it like - env GOOS=linux go build -ldflags="-s -w" -o bin/something cmd/main.go But, it failed to deserialize, and didn't print anything on an EC2 instance when using the same build command.

But then, I changed the var result map[string]string to var result map[string]interface{} and it worked on both my EC2 instance and mac.

I also had to typecast the interface{} object at the end before returning it.

func GetUserEmail(userID int) string {
    resp := getFromSomething("https://something/users/" + strconv.Itoa(userID))
    var result map[string]interface{}

    json.NewDecoder(resp.Body).Decode(&result)
    log.Printf("userEmail: %s", result["email"])
    return result["email"].(string)
}

Has anyone seen things like this before? Or, does anyone know why this happened?

I understand that the payload can always be represented better by var result map[string]interface{}, but my question is - why did that earlier representation of var result map[string]string work on the Mac and not on EC2?

Go version on Mac - go version go1.11.2 darwin/amd64 and that on EC2 is go version go1.10.3 linux/amd64

  • 写回答

1条回答 默认 最新

  • dou11655853 2018-12-13 00:35
    关注

    Always check for and handle errors.

    The error returned from Decode explains the problem. The application is attempting to decode numbers, booleans and arrays to string values.

    var v map[string]string
    err := json.NewDecoder(data).Decode(&v) // data is the JSON document from the question
    fmt.Println(err)  // prints json: cannot unmarshal number into Go value of type string
    

    Run it on the Playground.

    This issue is not platform specific. I have a couple of guesses why you saw different results:

    • Different JSON documents were used when testing on the different platforms.
    • The question states that the command env GOOS=linux go build -ldflags="-s -w" -o bin/something cmd/main.go was used to build the Mac version, but this command does not build a binary that's executable on the Mac. Perhaps you were not running the code you thought you were running.

    Either decode to map[string]interface{} as you discovered or decode to a struct with the one field you want:

    var v struct{ Email string }
    if err := json.NewDecoder(data).Decode(&v); err != nil {
        // handle error
    }
    fmt.Println(v.Email) // prints the decoded email value.
    

    Run it on the Playground.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机