Loop through CSV file and place into Variable that is used in an API function

Hello,

I could use some assistance.

Goal: Read a CSV file (will only have one “row” of data). Each row is a phone number. The program will take this phone number and plug it into an API that will then write the results to a CSV file. The files can be large (10’s of thousands of numbers).

I have basically have two pieces of code. 1 Reads the CSV file and prints the numbers to the screen. The other one trigger’s the API and prints the results into a CSV file. I am trying to combine the two to get the results I am looking for, but I am stuck. Thank you for any help.

Read CSV File Code Example:

package main

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

type CsvLine struct {
    Column1 string
}

func main() {

    filename := "input.csv"

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

    // Read File into a Variable
    lines, err := csv.NewReader(f).ReadAll()
    if err != nil {
        panic(err)
    }

    // Loop through lines & turn into object
    for _, line := range lines {
        data := CsvLine{
            Column1: line[0],
        }
        fmt.Println(data.Column1)
    }
}

This Code does the API lookup.

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

If you want to do this serially (and not in parallel), instead of printing in your first main(), you should call carrierlookup() (modify it to carrierlookup(phoneNumber string) and make use of the parameter).

The returned data you can decode (like you do in the second main()) and write to your resulting CSV file.

Then you can have fun making this parallel with two channels and some workers…

1 Like

Thank you for the tips. I have been working on Trying to get it to work in the manner suggested. However, I am still just learning and in general programming - Could you provide possibly a little more details on what the format might look like?

Again I appreciate all your help.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.