1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
package csvutil_test
import (
"bytes"
"encoding/csv"
"fmt"
"io"
"log"
"github.com/jszwec/csvutil"
)
// Value defines one record in the csv input. In this example it is important
// that Type field is defined before Value. Decoder reads headers and values
// in the same order as struct fields are defined.
type Value struct {
Type string `csv:"type"`
Value interface{} `csv:"value"`
}
func ExampleDecoder_interfaceValues() {
// lets say our csv input defines variables with their types and values.
data := []byte(`
type,value
string,string_value
int,10
`)
dec, err := csvutil.NewDecoder(csv.NewReader(bytes.NewReader(data)))
if err != nil {
log.Fatal(err)
}
// we would like to read every variable and store their already parsed values
// in the interface field. We can use Decoder.Map function to initialize
// interface with proper values depending on the input.
var value Value
dec.Map = func(field, column string, v interface{}) string {
if column == "type" {
switch field {
case "int": // csv input tells us that this variable contains an int.
var n int
value.Value = &n // lets initialize interface with an initialized int pointer.
default:
return field
}
}
return field
}
for {
value = Value{}
if err := dec.Decode(&value); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
if value.Type == "int" {
// our variable type is int, Map func already initialized our interface
// as int pointer, so we can safely cast it and use it.
n, ok := value.Value.(*int)
if !ok {
log.Fatal("expected value to be *int")
}
fmt.Printf("value_type: %s; value: (%T) %d\n", value.Type, value.Value, *n)
} else {
fmt.Printf("value_type: %s; value: (%T) %v\n", value.Type, value.Value, value.Value)
}
}
// Output:
// value_type: string; value: (string) string_value
// value_type: int; value: (*int) 10
}
|