Объединение значений карты в один json? - PullRequest
0 голосов
/ 09 июля 2020

Я изучаю Go и пытаюсь создать программу, которая берет веб-сайты, хранящиеся в csv, в столбец. Затем запрашивает http://ip-api.com, чтобы узнать, из какой страны происходит IP-адрес.

Однако проблема, с которой я сталкиваюсь, это мой JSON отображается следующим образом:

[{"country":"Singapore"}]
[{"country":"United States"},{"country":"United States"}]
[{"country":"Singapore"},{"country":"Singapore"},{"country":"Singapore"}]
[{"country":"Ireland"},{"country":"Ireland"},{"country":"Ireland"},{"country":"Ireland"}]

Но я хочу, чтобы он отображался вот так

{"country": "Singapore",
 "country": "United States"
 "country": "Ireland"
}

Мой CSV-файл выглядит так

www.google.com
www.bing.com
www.pokemon.com
www.yahoo.com

А вот мой код

package main

import (
    "encoding/csv"
    "encoding/json"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net/http"
    "os"
)

func closeFile(f *os.File) {
    err := f.Close()
    if err != nil {
        fmt.Fprintf(os.Stderr, "error: %v\n", err)
        os.Exit(1)
    }
}
func main() {
    m := make(map[string]string)
    result := []map[string]string{}

    csvFile, err :=
        os.Open("test.csv")
    if err != nil {
        log.Fatal(err)
    }
    defer closeFile(csvFile)
    reader := csv.NewReader(csvFile)
    for {
        line, err := reader.Read()
        if err == io.EOF {
            break
        } else if err != nil {
            log.Fatal(err)
        }

        response, err := http.Get(fmt.Sprintf("http://ip-api.com/json/%s?fields=org", line[0]))
        if err != nil {
            fmt.Println(err)
            defer response.Body.Close()

        } else {
            data, _ := ioutil.ReadAll(response.Body)
            err := json.Unmarshal(data, &m)
            if err != nil {
                panic(err)
            }
            result = append(result, m)
            rest, _ := json.Marshal(result)
            fmt.Println(string(rest)) **
        }

    }

}

Мне кажется, проблема в том, что мне не хватает for: range l oop для компиляции всего перед печатью, но я хотел бы получить любую обратную связь, чтобы решить эту проблему.

1 Ответ

0 голосов
/ 13 июля 2020

Это потому, что Go maps имеют семантику указателя , они не являются значениями:

Типы карт являются ссылочными типами, такими как указатели или срезы.

После того, как map создан с помощью make до того, как l oop будет запущен и будет appended в списке внутри l oop, это, по сути, указатель на те же самые базовые данные, хранящиеся в списке несколько раз.

Тогда Unmarshal не будет создавать новую карту, он будет повторно использовать тот же указатель, что означает перезапись ранее полученного результата.

Итак, исправление

Повторно создавать карту на каждой итерации. Просто переместите строку m := make(map[string]string) внутрь l oop, прямо перед вызовом API.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...