Платформа конкретной десериализации в Голанге? - PullRequest
0 голосов
/ 13 декабря 2018

Я запускаю REST API и получаю некоторые данные обратно.Я вчера столкнулся с интересным поведением.Я еще не понял точную причину этого.Который я пытаюсь найти здесь.Для полезной нагрузки, которая выглядит как -

{
    "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": ""
}

Я использовал функцию, подобную приведенной ниже, для получения электронной почты -

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"]
}

Код отлично работал на моем Mac, где я его собирал, как -env GOOS=linux go build -ldflags="-s -w" -o bin/something cmd/main.go Но он не смог десериализоваться и ничего не печатал на экземпляре EC2 при использовании той же команды сборки.

Но затем я изменил var result map[string]string на var result map[string]interface{}, и он работали мой экземпляр EC2 и Mac.

Мне также пришлось в конце набрать объект interface{} перед его возвратом.

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)
}

Кто-нибудь видел подобные вещи раньше?Или кто-нибудь знает, почему это произошло?

Я понимаю, что полезная нагрузка всегда может быть лучше представлена ​​var result map[string]interface{}, , но мой вопрос - почему это раннее представление var result map[string]stringработать на Mac, а не на EC2?

Версия Go на Mac - go version go1.11.2 darwin/amd64, а на EC2 - go version go1.10.3 linux/amd64

1 Ответ

0 голосов
/ 13 декабря 2018

Всегда проверяйте и обрабатывайте ошибки.

Ошибка, возвращаемая декодером, объясняет проблему.Приложение пытается декодировать числа, логические значения и массивы в строковые значения.

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

Запустить его на игровой площадке .

Эта проблема не зависит от платформы.У меня есть пара предположений, почему вы видели разные результаты:

  • При тестировании на разных платформах использовались разные документы JSON.
  • В вопросе говорится, что использовалась команда env GOOS=linux go build -ldflags="-s -w" -o bin/something cmd/main.goдля сборки версии для Mac, но эта команда не создает двоичный файл, исполняемый на Mac.Возможно, вы не выполняли код, который, как вы думали, выполняли.

Либо декодируйте до map[string]interface{}, как вы обнаружили, либо декодируйте в структуру с одним нужным вам полем:

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.

Запустите его на игровой площадке .

...