I have a bunch of either IP ranges or single addresses. I figured out how to loop through them, I can successfully print them to the console. However, when i write the same data to CSV, it magically adds a comma after every value (instead of adding them all under the same header separated by a space). I'm following all the rules (well, seemingly, anyway) to appending data in Go, but i just can't figure out why this isn't working. I'm assuming the CSV function in Go just see's a space and thinks it should be separated by a comma.
The input
part of this is looping through addresses that are []string
types. So one value could be 127.0.0.1 - 127.0.0.255
or just 127.0.0.1
. I just want them to look like this in the csv column Included
: 127.0.0.1 - 127.0.0.255 127.0.0.1
Screenshot of how the data appears in the console (correct):
Screenshot of the CSV (not correct):
I want the example CSV to look like this:
Here is the code i'm working with right now. If more is needed, let me know, but this is how i'm writing the data to CSV.
func ToCsv(inputs []interface{}, output io.Writer) {
w := csv.NewWriter(output)
defer w.Flush()
if len(inputs) == 0 {
return
} else {
// Get Header
r := reflect.ValueOf(inputs[0])
val := reflect.Indirect(reflect.ValueOf(inputs[0]))
var headers []string
for i := 0; i < r.NumField(); i++ {
headers = append(headers, val.Type().Field(i).Name)
}
w.Write(headers)
// Get Content
for _, input := range inputs {
ri := reflect.ValueOf(input)
var result []string
for i := 0; i < ri.NumField(); i++ {
switch ri.Field(i).Interface().(type) {
case []string:
//this is the part that's looping through all the ip addresses and is causing me a headache
stringArray := ri.Field(i).Interface().([]string)
for ii := 0; ii < len(stringArray); ii++ {
stringArray[ii] = strings.Replace(stringArray[ii], " ", ":", -1)
result = append(result,stringArray[ii])
}
case bool:
result = append(result, strconv.FormatBool(ri.Field(i).Interface().(bool)))
case int32:
result = append(result, strconv.FormatInt(int64(ri.Field(i).Interface().(int32)), 10))
case []int32:
intArray := ri.Field(i).Interface().([]int32)
for ii := 0; ii < len(intArray); ii++ {
result = append(result, strconv.FormatInt(int64(intArray[ii]),10))
}
case string:
result = append(result, ri.Field(i).Interface().(string))
default:
result = append(result, "")
}
}
w.Write(result)
}
}
}
In-order to get the output of data without comma, csv reader has a variable known as, Comma
, which sets the byte which separates values in csv.
The same goes for both csv reader and writer.
For csv data with other than comma, you need to set Comma
variable of reader or writer respectively.
package main
import (
"encoding/csv"
"os"
"strings"
)
func main() {
// temporary csv
sr := strings.NewReader(
`"name" "value"
"nilsocket" "7"
"nil" "77"
`)
// set your src of csv
r := csv.NewReader(sr)
r.Comma = ' ' // set this if your values were seperated
// with anything other than ','(comma)
res, _ := r.ReadAll() // read csv, res is going to be [][]string type
// you can fetch one record with r.Read()
// don't forget to check for errors
w := csv.NewWriter(os.Stdout) // set your dst for csv
w.Comma = ' ' // set the Comma byte to space
w.WriteAll(res) // write csv
w.Flush() // don't forget to flush
}