Golang中如何接收数组请求并逐个返回响应

Golang中如何接收数组请求并逐个返回响应 我遇到一个需求,用户可以通过数组中的一个键传递多个值。我希望应用程序能对数组中的每个值运行验证,并相应地打印响应。

示例输入:

{
    "ticket": [
        "abc",
        "def",
        "ghi",
    ],
    "user": "xyzasb"
}

我希望将票据 [abc, def, ghi] 作为输入变量传递给一个使用 GET 方法的第三方 API,并将收到的响应一个接一个地打印出来。

8 回复

请展示代码

更多关于Golang中如何接收数组请求并逐个返回响应的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


有人能帮我解决这个问题吗

我不太明白你的问题。你对这个要求的哪一部分有疑问?你已经实现了哪些部分,还缺少什么?

感谢Yamil,实际上需求是根据工单类型来决定是使用INC搜索还是CHG搜索,并将两种工单的响应结果一个接一个地打印出来。

我当前的实现仅接受键“ticket”的单个值并给出响应。现在我希望该键的值可以是多个数组,并为每个值返回所需的响应。

你可以使用一个映射(Map)来关联你的票据与响应。 我的意思是,获取 snowapiresp 的值并将其存储在一个映射中,例如:

m = make(map[string]*Response)
key := fmt.Sprintf(SnowInc + SnowTicket)
m[key] = nil
// 处理URL,当你获得snowapiresp时,将其存储在你的映射中
m[key] = snowapiresp

请求数据类似这样

{
"tickets": [  "INC0012345678",
"CHG0012345678",
"CHG0012345679",
"INC0012345679"
],
"IncludeDetail": true,
"mwuser": "abcd"
}

第三方 API 的 URL 根据工单类型而有所不同:如果前三个字符是 “INC”,则调用 URL = A;如果是 “CHG”,则调用 URL = B。

基于选定的 URL,我将执行 client.Get

//Third Party SNOW API Call
var snowapiresp *http.Response
if strings.Contains(SnowTicket, "INC") {
snowapiresp, err = client.Get(fmt.Sprintf(SnowInc + SnowTicket))
if err != nil {
fmt.Println(err.Error())
}
} else {
snowapiresp, _ = client.Get(fmt.Sprintf(SnowChg + SnowTicket))
if err != nil {
fmt.Println(err.Error())
}
}

并为每个工单号打印响应。

在Golang中处理数组请求并逐个返回响应,可以通过以下方式实现:

package main

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

// 请求结构体
type RequestData struct {
    Ticket []string `json:"ticket"`
    User   string   `json:"user"`
}

// API响应结构体(根据实际API调整)
type APIResponse struct {
    Data    interface{} `json:"data"`
    Success bool        `json:"success"`
}

func main() {
    http.HandleFunc("/process", processHandler)
    http.ListenAndServe(":8080", nil)
}

func processHandler(w http.ResponseWriter, r *http.Request) {
    // 解析请求体
    body, err := ioutil.ReadAll(r.Body)
    if err != nil {
        http.Error(w, "读取请求体失败", http.StatusBadRequest)
        return
    }
    
    var req RequestData
    if err := json.Unmarshal(body, &req); err != nil {
        http.Error(w, "JSON解析失败", http.StatusBadRequest)
        return
    }
    
    // 验证ticket数组
    if len(req.Ticket) == 0 {
        http.Error(w, "ticket数组不能为空", http.StatusBadRequest)
        return
    }
    
    // 设置响应头
    w.Header().Set("Content-Type", "application/json")
    
    // 使用WaitGroup等待所有goroutine完成
    var wg sync.WaitGroup
    responses := make([]APIResponse, len(req.Ticket))
    
    // 为每个ticket并发调用API
    for i, ticket := range req.Ticket {
        wg.Add(1)
        go func(idx int, tkt string) {
            defer wg.Done()
            
            // 调用第三方API
            resp, err := callThirdPartyAPI(tkt)
            if err != nil {
                responses[idx] = APIResponse{
                    Data:    fmt.Sprintf("调用API失败: %v", err),
                    Success: false,
                }
                return
            }
            
            responses[idx] = resp
        }(i, ticket)
    }
    
    wg.Wait()
    
    // 返回所有响应
    json.NewEncoder(w).Encode(responses)
}

func callThirdPartyAPI(ticket string) (APIResponse, error) {
    // 构建API URL
    apiURL := fmt.Sprintf("https://api.example.com/ticket/%s", ticket)
    
    // 发送GET请求
    resp, err := http.Get(apiURL)
    if err != nil {
        return APIResponse{}, err
    }
    defer resp.Body.Close()
    
    // 读取响应
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return APIResponse{}, err
    }
    
    var apiResp APIResponse
    if err := json.Unmarshal(body, &apiResp); err != nil {
        return APIResponse{}, err
    }
    
    return apiResp, nil
}

如果需要逐个流式返回响应(而不是等待所有完成),可以使用Server-Sent Events:

func streamHandler(w http.ResponseWriter, r *http.Request) {
    // ... 解析请求部分同上 ...
    
    // 设置SSE头
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")
    
    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
        return
    }
    
    // 为每个ticket调用API并立即返回
    for _, ticket := range req.Ticket {
        resp, err := callThirdPartyAPI(ticket)
        var result string
        if err != nil {
            result = fmt.Sprintf(`{"ticket":"%s","error":"%v"}`, ticket, err)
        } else {
            jsonData, _ := json.Marshal(resp)
            result = fmt.Sprintf(`{"ticket":"%s","response":%s}`, ticket, string(jsonData))
        }
        
        // 发送SSE格式数据
        fmt.Fprintf(w, "data: %s\n\n", result)
        flusher.Flush()
    }
}

对于简单的顺序处理:

func sequentialHandler(w http.ResponseWriter, r *http.Request) {
    // ... 解析请求部分同上 ...
    
    w.Header().Set("Content-Type", "application/json")
    
    var responses []map[string]interface{}
    for _, ticket := range req.Ticket {
        resp, err := callThirdPartyAPI(ticket)
        if err != nil {
            responses = append(responses, map[string]interface{}{
                "ticket":  ticket,
                "error":   err.Error(),
                "success": false,
            })
        } else {
            responses = append(responses, map[string]interface{}{
                "ticket":  ticket,
                "data":    resp.Data,
                "success": resp.Success,
            })
        }
    }
    
    json.NewEncoder(w).Encode(responses)
}
回到顶部