Golang中如何遍历CSV文件并将数据存入API函数使用的变量

Golang中如何遍历CSV文件并将数据存入API函数使用的变量 我需要帮助。

目标:读取一个CSV文件(只包含一行数据)。每行是一个电话号码。程序将获取这个电话号码并将其插入到一个API中,然后将结果写入CSV文件。文件可能很大(数万个号码)。

我基本上有两段代码。一段读取CSV文件并将号码打印到屏幕上。另一段触发API并将结果打印到CSV文件中。我正在尝试将两者结合起来以获得我想要的结果,但遇到了困难。感谢任何帮助。

读取CSV文件的代码示例:

package main

import (
    "encoding/csv"
    "fmt"
    "os"
)

type CsvLine struct {
    Column1 string
}

func main() {

    filename := "input.csv"

    // 打开CSV文件
    f, err := os.Open(filename)
    if err != nil {
        panic(err)
    }
    defer f.Close()

    // 将文件读入变量
    lines, err := csv.NewReader(f).ReadAll()
    if err != nil {
        panic(err)
    }

    // 遍历行并转换为对象
    for _, line := range lines {
        data := CsvLine{
            Column1: line[0],
        }
        fmt.Println(data.Column1)
    }
}

这段代码执行API查询:

package main

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



func decodeJson(m map[string]interface{}) []string {
    values := make([]string, 0, len(m))
    for _, v := range m {
        switch vv := v.(type) {
        case map[string]interface{}:
            for _, value := range decodeJson(vv) {
                values = append(values, value)
            }
        case string:
            values = append(values, vv)
        case float64:
            values = append(values, strconv.FormatFloat(vv, 'f', -1, 64))
        case []interface{}:

        case bool:
            values = append(values, strconv.FormatBool(vv))
        case nil:
            values = append(values, "nil")
        }
    }
    return values
}


func carrierlookup() []byte {

    url := "https://api.message360.com/api/v3/carrier/lookup.json"

    payload := strings.NewReader("phoneNumber=")

    req, _ := http.NewRequest("POST", url, payload)

    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    req.Header.Add("Authorization", "Basic ")
    req.Header.Add("Cache-Control", "no-cache")

    res, _ := http.DefaultClient.Do(req)

    defer res.Body.Close()
    body, _ := ioutil.ReadAll(res.Body)

    return body

}



func main() {


    var d interface{}
    err := json.Unmarshal(carrierlookup(), &d)
    if err != nil {
        log.Fatal("Failed to unmarshal")
    }
    values := decodeJson(d.(map[string]interface{}))
    fmt.Println(values)

    f, err := os.Create("outputfile.csv")
    if err != nil {
        log.Fatal("Failed to create outputfile.csv")
    }
    defer f.Close()
    w := csv.NewWriter(f)
    if err := w.Write(values); err != nil {
        log.Fatal("Failed to write to file")
    }
    w.Flush()
    if err := w.Error(); err != nil {
        log.Fatal("Failed to flush outputfile.csv")
    }
}

更多关于Golang中如何遍历CSV文件并将数据存入API函数使用的变量的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

感谢您的建议。我一直在尝试按照建议的方式使其工作。然而,我仍在学习通用编程的过程中——您能否稍微详细说明一下可能的格式是什么样的?

再次感谢您的所有帮助。

更多关于Golang中如何遍历CSV文件并将数据存入API函数使用的变量的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果您想以串行方式(而非并行)执行此操作,不应在第一个 main() 函数中直接打印,而应调用 carrierlookup() 函数(将其修改为 carrierlookup(phoneNumber string) 并利用该参数)。

返回的数据可以按照您在第二个 main() 函数中的处理方式进行解码,并写入结果 CSV 文件。

之后您就可以尝试使用两个通道和一些工作器来实现并行处理,这会很有趣…

以下是结合两段代码的解决方案,用于遍历CSV文件中的电话号码,调用API查询,并将结果写入新的CSV文件。该方案考虑了处理大文件时的内存效率,通过逐行读取而非一次性加载全部数据。

package main

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

type CsvLine struct {
    Column1 string
}

func decodeJson(m map[string]interface{}) []string {
    values := make([]string, 0, len(m))
    for _, v := range m {
        switch vv := v.(type) {
        case map[string]interface{}:
            for _, value := range decodeJson(vv) {
                values = append(values, value)
            }
        case string:
            values = append(values, vv)
        case float64:
            values = append(values, strconv.FormatFloat(vv, 'f', -1, 64))
        case []interface{}:
            // 处理数组情况,根据需要添加逻辑
        case bool:
            values = append(values, strconv.FormatBool(vv))
        case nil:
            values = append(values, "nil")
        }
    }
    return values
}

func carrierlookup(phoneNumber string) []byte {
    url := "https://api.message360.com/api/v3/carrier/lookup.json"
    payload := strings.NewReader("phoneNumber=" + phoneNumber)

    req, err := http.NewRequest("POST", url, payload)
    if err != nil {
        log.Fatal("Failed to create request: ", err)
    }

    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    req.Header.Add("Authorization", "Basic YOUR_AUTH_TOKEN") // 替换为实际授权信息
    req.Header.Add("Cache-Control", "no-cache")

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal("API request failed: ", err)
    }
    defer res.Body.Close()

    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        log.Fatal("Failed to read response body: ", err)
    }

    return body
}

func main() {
    inputFilename := "input.csv"
    outputFilename := "outputfile.csv"

    // 打开输入CSV文件
    inputFile, err := os.Open(inputFilename)
    if err != nil {
        log.Fatal("Failed to open input file: ", err)
    }
    defer inputFile.Close()

    // 创建输出CSV文件
    outputFile, err := os.Create(outputFilename)
    if err != nil {
        log.Fatal("Failed to create output file: ", err)
    }
    defer outputFile.Close()

    reader := csv.NewReader(inputFile)
    writer := csv.NewWriter(outputFile)
    defer writer.Flush()

    // 逐行读取输入文件
    for {
        line, err := reader.Read()
        if err != nil {
            if err.Error() == "EOF" {
                break
            }
            log.Fatal("Error reading CSV line: ", err)
        }

        if len(line) == 0 {
            continue
        }

        data := CsvLine{
            Column1: line[0],
        }

        // 调用API查询
        apiResponse := carrierlookup(data.Column1)

        var jsonData interface{}
        err = json.Unmarshal(apiResponse, &jsonData)
        if err != nil {
            log.Printf("Failed to unmarshal API response for %s: %v", data.Column1, err)
            continue
        }

        values := decodeJson(jsonData.(map[string]interface{}))

        // 写入结果到输出文件
        if err := writer.Write(values); err != nil {
            log.Fatal("Failed to write to output file: ", err)
        }
    }

    if err := writer.Error(); err != nil {
        log.Fatal("Error flushing output file: ", err)
    }

    fmt.Println("Processing completed. Results written to", outputFilename)
}

关键改进说明:

  1. 逐行处理:使用reader.Read()替代ReadAll(),避免将整个文件加载到内存,适用于大文件。
  2. API集成:修改carrierlookup函数以接受电话号码参数,并在主循环中为每个号码调用API。
  3. 错误处理:添加了API请求和响应的错误检查,确保程序在遇到问题时不会崩溃。
  4. 输出写入:在循环中逐行将API结果写入输出CSV文件,使用defer writer.Flush()确保所有数据被写入。

注意:替换YOUR_AUTH_TOKEN为实际的API授权信息。根据API响应结构,可能需要调整decodeJson函数以正确提取所需字段。如果API返回数组结构,需在case []interface{}分支中添加处理逻辑。

回到顶部