Golang如何合并HTTP JSON响应

Golang如何合并HTTP JSON响应 你好,

在Go语言中,通过for循环对一组链接执行HTTP GET请求,将每个HTTP JSON响应的输出合并到一个单一的数组对象中,最佳方法是什么?

for i := 0; i < len(servers.Sites); i++ {
    		req, err := http.NewRequest(http.MethodGet, servers.Sites[i].URLs, nil)

    		if err != nil {
    			log.Println(err)
    		}
    }

我希望看到响应合并到一个对象中,就像这样,在“vm”对象下:

output := Output{
            Success:   true,
            Vm:        <JSON outputs here, each separated by comma>
        }

更多关于Golang如何合并HTTP JSON响应的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

是的。根据您的建议,它成功运行了。感谢您的帮助!

更多关于Golang如何合并HTTP JSON响应的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你是否已将 google.com 替换为一个实际会返回 JSON 数据的 URL?

感谢肖恩。我在我的笔记本电脑上的Go引擎中尝试了它,得到了:

{true [invalid character '<' looking for beginning of value]}

这是否符合你的需求?根据我在Go Playground上遇到的错误,看起来那个环境并未配置为允许发起网络请求,所以我不确定它是否准确。

https://play.golang.org/p/ZghU8fuV3Jf

在Go中合并多个HTTP JSON响应,可以通过以下方式实现:

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "sync"
)

type Output struct {
    Success bool        `json:"success"`
    Vm      []interface{} `json:"vm"`
}

type Site struct {
    URLs string `json:"urls"`
}

type Servers struct {
    Sites []Site `json:"sites"`
}

func fetchAndMergeJSON(servers Servers) (*Output, error) {
    var (
        wg sync.WaitGroup
        mu sync.Mutex
        output Output
    )

    output.Vm = make([]interface{}, 0, len(servers.Sites))
    output.Success = true

    for _, site := range servers.Sites {
        wg.Add(1)
        go func(url string) {
            defer wg.Done()

            resp, err := http.Get(url)
            if err != nil {
                mu.Lock()
                output.Success = false
                mu.Unlock()
                return
            }
            defer resp.Body.Close()

            body, err := io.ReadAll(resp.Body)
            if err != nil {
                mu.Lock()
                output.Success = false
                mu.Unlock()
                return
            }

            var jsonData interface{}
            if err := json.Unmarshal(body, &jsonData); err != nil {
                mu.Lock()
                output.Success = false
                mu.Unlock()
                return
            }

            mu.Lock()
            output.Vm = append(output.Vm, jsonData)
            mu.Unlock()
        }(site.URLs)
    }

    wg.Wait()
    return &output, nil
}

func main() {
    servers := Servers{
        Sites: []Site{
            {URLs: "https://api.example.com/data1"},
            {URLs: "https://api.example.com/data2"},
            {URLs: "https://api.example.com/data3"},
        },
    }

    result, err := fetchAndMergeJSON(servers)
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }

    jsonOutput, _ := json.MarshalIndent(result, "", "  ")
    fmt.Println(string(jsonOutput))
}

如果需要保持顺序,可以使用带缓冲的通道:

func fetchAndMergeJSONOrdered(servers Servers) (*Output, error) {
    type result struct {
        index int
        data  interface{}
        err   error
    }

    ch := make(chan result, len(servers.Sites))
    var wg sync.WaitGroup

    for i, site := range servers.Sites {
        wg.Add(1)
        go func(idx int, url string) {
            defer wg.Done()

            resp, err := http.Get(url)
            if err != nil {
                ch <- result{index: idx, err: err}
                return
            }
            defer resp.Body.Close()

            body, err := io.ReadAll(resp.Body)
            if err != nil {
                ch <- result{index: idx, err: err}
                return
            }

            var jsonData interface{}
            if err := json.Unmarshal(body, &jsonData); err != nil {
                ch <- result{index: idx, err: err}
                return
            }

            ch <- result{index: idx, data: jsonData}
        }(i, site.URLs)
    }

    wg.Wait()
    close(ch)

    output := &Output{
        Success: true,
        Vm:      make([]interface{}, len(servers.Sites)),
    }

    for res := range ch {
        if res.err != nil {
            output.Success = false
        }
        if res.data != nil {
            output.Vm[res.index] = res.data
        }
    }

    return output, nil
}

对于需要处理特定JSON结构的情况:

type VMData struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
    // 其他字段...
}

func fetchStructuredJSON(servers Servers) (*Output, error) {
    var (
        wg     sync.WaitGroup
        mu     sync.Mutex
        output Output
    )

    output.Vm = make([]VMData, 0, len(servers.Sites))
    output.Success = true

    for _, site := range servers.Sites {
        wg.Add(1)
        go func(url string) {
            defer wg.Done()

            resp, err := http.Get(url)
            if err != nil {
                mu.Lock()
                output.Success = false
                mu.Unlock()
                return
            }
            defer resp.Body.Close()

            var vmData VMData
            if err := json.NewDecoder(resp.Body).Decode(&vmData); err != nil {
                mu.Lock()
                output.Success = false
                mu.Unlock()
                return
            }

            mu.Lock()
            output.Vm = append(output.Vm.([]VMData), vmData)
            mu.Unlock()
        }(site.URLs)
    }

    wg.Wait()
    return &output, nil
}
回到顶部