File: example_decoder_interface_test.go

package info (click to toggle)
golang-github-jszwec-csvutil 1.7.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 396 kB
  • sloc: makefile: 2
file content (75 lines) | stat: -rw-r--r-- 1,916 bytes parent folder | download
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
}