### Configure TSV and Custom Delimiters with csvutil Source: https://context7.com/jszwec/csvutil/llms.txt Shows how to read and write TSV (tab-separated values) files using csvutil by setting a custom delimiter. The example includes struct mapping and demonstrates both decoding and encoding operations. ```go package main import ( "bytes" "encoding/csv" "fmt" "io" "log" "strings" "github.com/jszwec/csvutil" ) type User struct { Name string `csv:"name"` Age int `csv:"age"` City string `csv:"city"` } func main() { // Reading TSV tsvData := "name\tage\tcity\nJohn\t30\tBoston\nAlice\t25\tSF" csvReader := csv.NewReader(strings.NewReader(tsvData)) csvReader.Comma = '\t' // Set tab as delimiter dec, err := csvutil.NewDecoder(csvReader) if err != nil { log.Fatal(err) } var users []User for { var u User if err := dec.Decode(&u); err == io.EOF { break } else if err != nil { log.Fatal(err) } users = append(users, u) } // Writing TSV var buf bytes.Buffer w := csv.NewWriter(&buf) w.Comma = '\t' // Set tab as delimiter enc := csvutil.NewEncoder(w) for _, u := range users { if err := enc.Encode(u); err != nil { fmt.Println("error:", err) return } } w.Flush() if err := w.Error(); err != nil { fmt.Println("error:", err) return } fmt.Println(buf.String()) // Output: // name age city // John 30 Boston // Alice 25 SF } ``` -------------------------------- ### Custom CSV unmarshaling with Go generics Source: https://context7.com/jszwec/csvutil/llms.txt Shows how to register custom unmarshal functions for specific types using generics. Includes examples for parsing time values and hexadecimal numbers. Requires github.com/jszwec/csvutil package. ```go package main import ( "encoding/csv" "fmt" "io" "log" "strconv" "strings" "time" "github.com/jszwec/csvutil" ) type Record struct { Time time.Time `csv:"time"` HexNum int `csv:"hex"` } func main() { csvReader := csv.NewReader(strings.NewReader(`time,hex 03:04PM,1a 04:30PM,ff`)) dec, err := csvutil.NewDecoder(csvReader) if err != nil { log.Fatal(err) } // Custom time unmarshaler unmarshalTime := csvutil.UnmarshalFunc(func(data []byte, t *time.Time) error { parsed, err := time.Parse(time.Kitchen, string(data)) if err != nil { return err } *t = parsed return nil }) // Custom hex int unmarshaler unmarshalHex := csvutil.UnmarshalFunc(func(data []byte, n *int) error { val, err := strconv.ParseInt(string(data), 16, 64) if err != nil { return err } *n = int(val) return nil }) unmarshalers := csvutil.NewUnmarshalers(unmarshalTime, unmarshalHex) dec.WithUnmarshalers(unmarshalers) var records []Record for { var r Record if err := dec.Decode(&r); err == io.EOF { break } else if err != nil { log.Fatal(err) } records = append(records, r) } for _, r := range records { fmt.Printf("Time: %s, Hex: %d\n", r.Time.Format(time.Kitchen), r.HexNum) } // Output: // Time: 3:04PM, Hex: 26 // Time: 4:30PM, Hex: 255 } ``` -------------------------------- ### Inline Tag Prefix Functionality in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md Demonstrates the inline tag feature which allows specifying prefixes for embedded struct fields. Shows how multiple instances of the same struct type can be used with different prefixes. Includes omitempty tag example for optional fields. ```go package main import ( "fmt" "github.com/jszwec/csvutil" ) func main() { type Address struct { Street string `csv:"street"` City string `csv:"city"` } type User struct { Name string `csv:"name"` Address Address `csv:",inline"` HomeAddress Address `csv:"home_address_,inline"` WorkAddress Address `csv:"work_address_,inline"` Age int `csv:"age,omitempty"` } users := []User{ { Name: "John", Address: Address{"Washington", "Boston"}, HomeAddress: Address{"Boylston", "Boston"}, WorkAddress: Address{"River St", "Cambridge"}, Age: 26, }, } b, err := csvutil.Marshal(users) if err != nil { fmt.Println("error:", err) } fmt.Printf("%s\n", b) // Output: // name,street,city,home_address_street,home_address_city,work_address_street,work_address_city,age // John,Washington,Boston,Boylston,Boston,River St,Cambridge,26 } ``` -------------------------------- ### Implement Marshaler and Unmarshaler Interfaces Source: https://context7.com/jszwec/csvutil/llms.txt Demonstrates defining custom MarshalCSV and UnmarshalCSV methods on types to control how data is serialized/deserialized in CSV format. In this example, integers are encoded/decoded as hexadecimal strings. ```go package main import ( "fmt" "strconv" "github.com/jszwec/csvutil" ) // Custom type with hex encoding type HexInt int64 func (h HexInt) MarshalCSV() ([]byte, error) { return strconv.AppendInt(nil, int64(h), 16), nil } func (h *HexInt) UnmarshalCSV(data []byte) error { i, err := strconv.ParseInt(string(data), 16, 64) if err != nil { return err } *h = HexInt(i) return nil } type Record struct { Name string `csv:"name"` Value HexInt `csv:"value"` } func main() { // Marshal records := []Record{ {"item1", 255}, {"item2", 4095}, } b, err := csvutil.Marshal(records) if err != nil { fmt.Println("error:", err) return } fmt.Println("Marshaled:") fmt.Println(string(b)) // Unmarshal var decoded []Record if err := csvutil.Unmarshal(b, &decoded); err != nil { fmt.Println("error:", err) return } fmt.Println("Unmarshaled:") fmt.Printf("%+v\n", decoded) // Output: // Marshaled: // name,value // item1,ff // item2,fff // Unmarshaled: // [{Name:item1 Value:255} {Name:item2 Value:4095}] } ``` -------------------------------- ### Implement encoding.TextMarshaler/TextUnmarshaler Interfaces Source: https://github.com/jszwec/csvutil/blob/master/README.md Uses standard library encoding interfaces for text-based marshaling and unmarshaling. This approach integrates with Go's standard encoding patterns and provides compatibility with other encoding packages. The example demonstrates hexadecimal encoding for a custom type. These interfaces are checked after type-implemented registered interfaces. ```go type Foo int64 func (f Foo) MarshalText() ([]byte, error) { return strconv.AppendInt(nil, int64(f), 16), nil } func (f *Foo) UnmarshalText(data []byte) error { i, err := strconv.ParseInt(string(data), 16, 64) if err != nil { return err } *f = Foo(i) return nil } ``` -------------------------------- ### Register Interface-Based Marshalers for Generic Types Source: https://github.com/jszwec/csvutil/blob/master/README.md Demonstrates registering marshalers for interfaces rather than concrete types, enabling generic handling of types that implement specific interfaces. The example shows handling fmt.Stringer and fmt.Scanner interfaces with custom marshaling logic. Types implementing these registered interfaces will use the provided conversion functions. Interface-based registered types have second-highest precedence. ```go type Foo int64 func (f Foo) String() string { return strconv.FormatInt(int64(f), 16) } func (f *Foo) Scan(state fmt.ScanState, verb rune) error { // too long; look here: https://github.com/jszwec/csvutil/blob/master/example_decoder_register_test.go#L19 } enc.WithMarshalers( csvutil.MarshalFunc(func(s fmt.Stringer) ([]byte, error) { return []byte(s.String()), nil }), ) dec.WithUnmarshalers( csvutil.UnmarshalFunc(func(data []byte, s fmt.Scanner) error { _, err := fmt.Sscan(string(data), s) return err }), ) ``` -------------------------------- ### Nested Embedded Structs Handling in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md Shows how csvutil handles nested and embedded structs during CSV marshaling and unmarshaling. Demonstrates automatic flattening of embedded struct fields into the parent CSV structure. Includes both encoding and decoding examples. ```go package main import ( "fmt" "github.com/jszwec/csvutil" ) type Address struct { Street string `csv:"street"` City string `csv:"city"` } type User struct { Name string `csv:"name"` Address } func main() { users := []User{ { Name: "John", Address: Address{ Street: "Boylston", City: "Boston", }, }, } b, err := csvutil.Marshal(users) if err != nil { panic(err) } fmt.Printf("%s\n", b) var out []User if err := csvutil.Unmarshal(b, &out); err != nil { panic(err) } fmt.Printf("%+v\n", out) // Output: // // name,street,city // John,Boylston,Boston // // [{Name:John Address:{Street:Boylston City:Boston}}] } ``` -------------------------------- ### Implement csvutil.Marshaler/Unmarshaler Interfaces Source: https://github.com/jszwec/csvutil/blob/master/README.md Defines custom marshaling and unmarshaling behavior by implementing the csvutil.Marshaler and/or csvutil.Unmarshaler interfaces. This approach allows direct control over CSV encoding/decoding for custom types. The example shows a Foo type that marshals to/from hexadecimal format. These interfaces are checked after registered interfaces but before encoding.Text interfaces. ```go type Foo int64 func (f Foo) MarshalCSV() ([]byte, error) { return strconv.AppendInt(nil, int64(f), 16), nil } func (f *Foo) UnmarshalCSV(data []byte) error { i, err := strconv.ParseInt(string(data), 16, 64) if err != nil { return err } *f = Foo(i) return nil } ``` -------------------------------- ### Unmarshal CSV to Go Struct Slice in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md This example unmarshals CSV bytes to a slice of User structs using csvutil.Unmarshal with default csv.Reader settings. It maps CSV columns to struct fields via tags, handles optional integer fields (defaulting to zero), and parses time.Time from ISO format. Outputs the parsed users for verification. ```go var csvInput = []byte(` name,age,CreatedAt jacek,26,2012-04-01T15:00:00Z john,,0001-01-01T00:00:00Z`, ) type User struct { Name string `csv:"name"` Age int `csv:"age,omitempty"` CreatedAt time.Time } var users []User if err := csvutil.Unmarshal(csvInput, &users); err != nil { fmt.Println("error:", err) } for _, u := range users { fmt.Printf("%+v\n", u) } // Output: // {Name:jacek Age:26 CreatedAt:2012-04-01 15:00:00 +0000 UTC} // {Name:john Age:0 CreatedAt:0001-01-01 00:00:00 +0000 UTC} ``` -------------------------------- ### Marshal Go Struct Slice to CSV in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md This example marshals a slice of User structs, including an embedded Address struct, to CSV bytes using csvutil.Marshal with default csv.Writer. It generates headers from struct tags, writes fields in order, and outputs empty strings for omitted optional fields and zero times. Suitable for simple CSV export without streaming. ```go type Address struct { City string Country string } type User struct { Name string Address Age int `csv:"age,omitempty"` CreatedAt time.Time } users := []User{ { Name: "John", Address: Address{"Boston", "USA"}, Age: 26, CreatedAt: time.Date(2010, 6, 2, 12, 0, 0, 0, time.UTC), }, { Name: "Alice", Address: Address{"SF", "USA"}, }, } b, err := csvutil.Marshal(users) if err != nil { fmt.Println("error:", err) } fmt.Println(string(b)) // Output: // Name,City,Country,age,CreatedAt // John,Boston,USA,26,2010-06-02T12:00:00Z // Alice,SF,USA,,0001-01-01T00:00:00Z ``` -------------------------------- ### Configure Custom Struct Tags for Encoder and Decoder Source: https://github.com/jszwec/csvutil/blob/master/README.md Configures the encoder and decoder to use custom struct field tags instead of the default 'csv' tag. This approach allows integration with existing struct definitions that use different tag names. The example demonstrates setting a custom tag name and applying it to both decoder and encoder configuration, enabling flexible field mapping. ```go type Foo struct { Bar int `custom:"bar"` } ``` ```go dec, err := csvutil.NewDecoder(r) if err != nil { log.Fatal(err) } dec.Tag = "custom" ``` ```go enc := csvutil.NewEncoder(w) enc.Tag = "custom" ``` -------------------------------- ### Register Custom Marshalers with Encoder/Decoder Source: https://github.com/jszwec/csvutil/blob/master/README.md Registers custom marshaler and unmarshaler functions using Encoder.WithMarshalers and Decoder.WithUnmarshalers. This approach allows runtime registration of conversion logic without modifying the original type. The example shows hexadecimal conversion using csvutil.MarshalFunc and UnmarshalFunc. Registered types take highest precedence in the processing order. ```go type Foo int64 enc.WithMarshalers( csvutil.MarshalFunc(func(f Foo) ([]byte, error) { return strconv.AppendInt(nil, int64(f), 16), nil }), ) dec.WithUnmarshalers( csvutil.UnmarshalFunc(func(data []byte, f *Foo) error { v, err := strconv.ParseInt(string(data), 16, 64) if err != nil { return err } *f = Foo(v) return nil }), ) ``` -------------------------------- ### Override Default Time Format via Registration Source: https://github.com/jszwec/csvutil/blob/master/README.md Customizes time.Time CSV formatting by registering custom marshaler and unmarshaler functions. This approach maintains compatibility with time.Time type while changing its string representation. The example uses a custom date/time format (2006/01/02 15:04:05) and demonstrates both encoder and decoder registration for consistent round-trip behavior. ```go const format = "2006/01/02 15:04:05" marshalTime := func(t time.Time) ([]byte, error) { return t.AppendFormat(nil, format), nil } unmarshalTime := func(data []byte, t *time.Time) error { tt, err := time.Parse(format, string(data)) if err != nil { return err } *t = tt return nil } enc := csvutil.NewEncoder(w) enc.Register(marshalTime) dec, err := csvutil.NewDecoder(r) if err != nil { return err } dec.Register(unmarshalTime) ``` -------------------------------- ### Create Custom Time Type with MarshalCSV/UnmarshalCSV Source: https://github.com/jszwec/csvutil/blob/master/README.md Implements custom time formatting by creating a wrapper type that embeds time.Time and provides custom CSV marshaling methods. This approach creates a distinct type that maintains time.Time functionality while providing controlled CSV serialization. The example shows implementing MarshalCSV and UnmarshalCSV for custom date format handling. ```go type Time struct { time.Time } const format = "2006/01/02 15:04:05" func (t Time) MarshalCSV() ([]byte, error) { var b [len(format)]byte return t.AppendFormat(b[:0], format), nil } func (t *Time) UnmarshalCSV(data []byte) error { tt, err := time.Parse(format, string(data)) if err != nil { return err } *t = Time{Time: tt} return nil } ``` -------------------------------- ### Decode CSV without header by providing custom header in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md When a CSV file lacks a header row, this example generates a header from a struct definition using csvutil.Header and passes it to the decoder. It demonstrates a full decode loop that works with optional fields using the omitempty tag. Ideal for legacy CSV formats with fixed column ordering. ```go type User struct { ID int Name string Age int `csv:",omitempty"` City string } csvReader := csv.NewReader(strings.NewReader(` 1,John,27,la 2,Bob,,ny`)) // in real application this should be done once in init function. userHeader, err := csvutil.Header(User{}, "csv") if err != nil { log.Fatal(err) } dec, err := csvutil.NewDecoder(csvReader, userHeader...) if err != nil { log.Fatal(err) } var users []User for { var u User if err := dec.Decode(&u); err == io.EOF { break } else if err != nil { log.Fatal(err) } users = append(users, u) } fmt.Printf("%+v", users) // Output: // [{ID:1 Name:John Age:27 City:la} {ID:2 Name:Bob Age:0 City:ny}] ``` -------------------------------- ### Configure custom CSV separator for Decoder and Encoder in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md Shows how to set a custom field delimiter (e.g., tab for TSV files) on both the csv.Reader and csv.Writer before creating a Decoder or Encoder with csvutil. The example includes a full decode loop and an encode loop that write records using the specified separator. Essential for handling non‑comma separated value files. ```go csvReader := csv.NewReader(r) csvReader.Comma = '\t' dec, err := csvutil.NewDecoder(csvReader) if err != nil { log.Fatal(err) } var users []User for { var u User if err := dec.Decode(&u); err == io.EOF { break } else if err != nil { log.Fatal(err) } users = append(users, u) } ``` ```go var buf bytes.Buffer w := csv.NewWriter(&buf) w.Comma = '\t' enc := csvutil.NewEncoder(w) for _, u := range users { if err := enc.Encode(u); err != nil { log.Fatal(err) } } w.Flush() if err := w.Error(); err != nil { log.Fatal(err) } ``` -------------------------------- ### Custom CSV marshaling with Go generics Source: https://context7.com/jszwec/csvutil/llms.txt Demonstrates registering custom marshal functions for specific types using generics. Handles time.Time formatting, hexadecimal integers, and fmt.Stringer implementations. Requires github.com/jszwec/csvutil package. ```go package main import ( "bytes" "encoding/csv" "fmt" "strconv" "time" "github.com/jszwec/csvutil" ) type Foo struct { Time time.Time `csv:"time"` Hex int `csv:"hex"` PtrHex *int `csv:"ptr_hex"` Buffer *bytes.Buffer `csv:"buffer"` } func main() { foos := []Foo{ { Time: time.Date(2020, 6, 20, 12, 0, 0, 0, time.UTC), Hex: 15, Buffer: bytes.NewBufferString("hello"), }, } // Register custom marshalers marshalInt := csvutil.MarshalFunc(func(n *int) ([]byte, error) { if n == nil { return []byte("NULL"), nil } return strconv.AppendInt(nil, int64(*n), 16), nil }) marshalTime := csvutil.MarshalFunc(func(t time.Time) ([]byte, error) { return t.AppendFormat(nil, time.Kitchen), nil }) marshalStringer := csvutil.MarshalFunc(func(s fmt.Stringer) ([]byte, error) { return []byte(s.String()), nil }) marshalers := csvutil.NewMarshalers(marshalInt, marshalTime, marshalStringer) var buf bytes.Buffer w := csv.NewWriter(&buf) enc := csvutil.NewEncoder(w) enc.WithMarshalers(marshalers) if err := enc.Encode(foos); err != nil { fmt.Println("error:", err) return } w.Flush() if err := w.Error(); err != nil { fmt.Println("error:", err) return } fmt.Println(buf.String()) // Output: // time,hex,ptr_hex,buffer // 12:00PM,f,NULL,hello } ``` -------------------------------- ### Flatten nested structs with CSV inline tags Source: https://context7.com/jszwec/csvutil/llms.txt Demonstrates using inline tags to flatten nested structs with custom column prefixes. Shows multiple address fields with different prefix configurations. Requires github.com/jszwec/csvutil package. ```go package main import ( "fmt" "github.com/jszwec/csvutil" ) type Address struct { Street string `csv:"street"` City string `csv:"city"` } type User struct { Name string `csv:"name"` Address Address `csv:",inline"` HomeAddress Address `csv:"home_address_,inline"` WorkAddress Address `csv:"work_address_,inline"` Age int `csv:"age,omitempty"` } func main() { users := []User{ { Name: "John", Address: Address{"Washington", "Boston"}, HomeAddress: Address{"Boylston", "Boston"}, WorkAddress: Address{"River St", "Cambridge"}, Age: 26, }, } b, err := csvutil.Marshal(users) if err != nil { fmt.Println("error:", err) return } fmt.Printf("%s", b) // Output: // name,street,city,home_address_street,home_address_city,work_address_street,work_address_city,age // John,Washington,Boston,Boylston,Boston,River St,Cambridge,26 } ``` -------------------------------- ### Normalize fields before decoding - Go Source: https://context7.com/jszwec/csvutil/llms.txt Uses Decoder.Map to transform CSV values prior to decoding, enabling normalization (e.g., converting "n/a" to "NaN"). Demonstrates per-field transformations for robust parsing. ```go package main import ( "encoding/csv" "fmt" "io" "log" "strings" "github.com/jszwec/csvutil" ) type Stats struct { Name string `csv:"name"` Score float64 `csv:"score"` } func main() { csvReader := csv.NewReader(strings.NewReader(`name,score alice,95.5 bob,n/a charlie,87.3`)) dec, err := csvutil.NewDecoder(csvReader) if err != nil { log.Fatal(err) } // Normalize "n/a" to "NaN" for float fields dec.Map = func(field, column string, v any) string { if _, ok := v.(float64); ok && strings.ToLower(field) == "n/a" { return "NaN" } return field } var stats []Stats for { var s Stats if err := dec.Decode(&s); err == io.EOF { break } else if err != nil { log.Fatal(err) } stats = append(stats, s) } for _, s := range stats { fmt.Printf("%s: %.1f\n", s.Name, s.Score) } // Output: // alice: 95.5 // bob: NaN // charlie: 87.3 } ``` -------------------------------- ### Encode structs to CSV (streaming) - Go Source: https://context7.com/jszwec/csvutil/llms.txt Streams struct encoding to CSV with automatic header generation and embedded struct support. Uses bytes.Buffer, csv.Writer, and csvutil.NewEncoder. Requires structs with csv tags and proper imports. ```go package main import ( "bytes" "encoding/csv" "fmt" "github.com/jszwec/csvutil" ) type Address struct { City string Country string } type User struct { Name string Address // embedded Age int `csv:"age,omitempty"` } func main() { users := []User{ {Name: "John", Address: Address{"Boston", "USA"}, Age: 26}, {Name: "Bob", Address: Address{"LA", "USA"}, Age: 27}, {Name: "Alice", Address: Address{"SF", "USA"}}, } var buf bytes.Buffer w := csv.NewWriter(&buf) enc := csvutil.NewEncoder(w) for _, u := range users { if err := enc.Encode(u); err != nil { fmt.Println("error:", err) return } } w.Flush() if err := w.Error(); err != nil { fmt.Println("error:", err) return } fmt.Println(buf.String()) // Output: // Name,City,Country,age // John,Boston,USA,26 // Bob,LA,USA,27 // Alice,SF,USA, } ``` -------------------------------- ### Marshal structs to CSV in Go Source: https://context7.com/jszwec/csvutil/llms.txt Encodes a slice of structs into CSV byte format with automatic header creation based on struct field names and tags. Supports embedded structs and omitempty tags. ```Go package main import ( "fmt" "time" "github.com/jszwec/csvutil" ) type Address struct { City string Country string } type User struct { Name string Address // embedded struct Age int `csv:"age,omitempty"` CreatedAt time.Time } func main() { users := []User{ { Name: "John", Address: Address{"Boston", "USA"}, Age: 26, CreatedAt: time.Date(2010, 6, 2, 12, 0, 0, 0, time.UTC), }, { Name: "Alice", Address: Address{"SF", "USA"}, }, } b, err := csvutil.Marshal(users) if err != nil { fmt.Println("error:", err) return } fmt.Println(string(b)) // Output: // Name,City,Country,age,CreatedAt // John,Boston,USA,26,2010-06-02T12:00:00Z // Alice,SF,USA,,0001-01-01T00:00:00Z } ``` -------------------------------- ### Generate CSV header from struct - Go Source: https://context7.com/jszwec/csvutil/llms.txt Builds a CSV header slice from a struct using csvutil.Header to decode headerless CSV files. Passes the generated header to NewDecoder and decodes rows into a typed slice. ```go package main import ( "encoding/csv" "fmt" "io" "log" "strings" "github.com/jszwec/csvutil" ) type User struct { ID int Name string Age int `csv:",omitempty"` City string } func main() { csvReader := csv.NewReader(strings.NewReader(`1,John,27,la 2,Bob,,ny`)) // Generate header from struct (do once, ideally in init) userHeader, err := csvutil.Header(User{}, "csv") if err != nil { log.Fatal(err) } // Pass generated header to decoder dec, err := csvutil.NewDecoder(csvReader, userHeader...) if err != nil { log.Fatal(err) } var users []User for { var u User if err := dec.Decode(&u); err == io.EOF { break } else if err != nil { log.Fatal(err) } users = append(users, u) } fmt.Printf("%+v", users) // Output: [{ID:1 Name:John Age:27 City:la} {ID:2 Name:Bob Age:0 City:ny}] } ``` -------------------------------- ### Stream CSV records with Decoder in Go Source: https://context7.com/jszwec/csvutil/llms.txt Streams decoding of large CSV files one record at a time using csvutil's Decoder. Works with any io.Reader that outputs CSV rows and handles EOF gracefully. ```Go package main import ( "encoding/csv" "fmt" "io" "log" "strings" "github.com/jszwec/csvutil" ) type User struct { ID *int `csv:"id,omitempty"` Name string `csv:"name"` City string `csv:"city"` Age int `csv:"age"` } func main() { csvReader := csv.NewReader(strings.NewReader(`id,name,age,city ,alice,25,la ,bob,30,ny`)) dec, err := csvutil.NewDecoder(csvReader) if err != nil { log.Fatal(err) } var users []User for { var u User if err := dec.Decode(&u); err == io.EOF { break } else if err != nil { log.Fatal(err) } users = append(users, u) } fmt.Println(users) // Output: [{ alice la 25} { bob ny 30}] } ``` -------------------------------- ### Capture unused CSV columns - Go Source: https://context7.com/jszwec/csvutil/llms.txt Collects unmapped CSV columns using Decoder.Header and Decoder.Unused, storing them in a map for later use. Requires a struct with a map field tagged csv:"-" and handling of io.EOF. ```go package main import ( "encoding/csv" "fmt" "io" "log" "strings" "github.com/jszwec/csvutil" ) type User struct { Name string `csv:"name"` City string `csv:"city"` Age int `csv:"age"` OtherData map[string]string `csv:"-"` } func main() { csvReader := csv.NewReader(strings.NewReader(`name,age,city,zip alice,25,la,90005 bob,30,ny,10005`)) dec, err := csvutil.NewDecoder(csvReader) if err != nil { log.Fatal(err) } header := dec.Header() var users []User for { u := User{OtherData: make(map[string]string)} if err := dec.Decode(&u); err == io.EOF { break } else if err != nil { log.Fatal(err) } // Store unused columns in the map for _, i := range dec.Unused() { u.OtherData[header[i]] = dec.Record()[i] } users = append(users, u) } fmt.Println(users) // Output: [{alice la 25 map[zip:90005]} {bob ny 30 map[zip:10005]}] } ``` -------------------------------- ### Decode all CSV records to slice in Go Source: https://context7.com/jszwec/csvutil/llms.txt Efficiently decodes entire CSV input into a slice of structs with a single Decode() call. Eliminates manual iteration when processing complete datasets. ```Go package main import ( "encoding/csv" "fmt" "log" "strings" "github.com/jszwec/csvutil" ) type User struct { ID *int `csv:"id,omitempty"` Name string `csv:"name"` City string `csv:"city"` Age int `csv:"age"` } func main() { csvReader := csv.NewReader(strings.NewReader(`id,name,age,city ,alice,25,la ,bob,30,ny`)) dec, err := csvutil.NewDecoder(csvReader) if err != nil { log.Fatal(err) } var users []User if err := dec.Decode(&users); err != nil { log.Fatal(err) } fmt.Println(users) // Output: [{ alice la 25} { bob ny 30}] } ``` -------------------------------- ### Custom Marshaler for Slice and Map Fields in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md Demonstrates how to implement custom Marshaler and Unmarshaler interfaces for slice and map types in csvutil. Shows how to handle comma-separated values for slices and map serialization. No default encoding exists for these types due to CSV spec limitations. ```go type Strings []string func (s Strings) MarshalCSV() ([]byte, error) { return []byte(strings.Join(s, ",")), nil // strings.Join takes []string but it will also accept Strings } type StringMap map[string]string func (sm StringMap) MarshalCSV() ([]byte, error) { return []byte(fmt.Sprint(sm)), nil } func main() { b, err := csvutil.Marshal([]struct { Strings Strings `csv:"strings"` Map StringMap `csv:"map"` }{ {[]string{"a", "b"}, map[string]string{"a": "1"}}, // no type casting is required for slice and map aliases {Strings{"c", "d"}, StringMap{"b": "1"}}, }) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", b) // Output: // strings,map // "a,b",map[a:1] // "c,d",map[b:1] } ``` -------------------------------- ### Unmarshal CSV to structs in Go Source: https://context7.com/jszwec/csvutil/llms.txt Decodes CSV byte data into a slice of structs using the first row as headers. Requires a Go struct with appropriate csv tags. Handles omitempty and time parsing automatically. ```Go package main import ( "fmt" "time" "github.com/jszwec/csvutil" ) type User struct { Name string `csv:"name"` Age int `csv:"age,omitempty"` CreatedAt time.Time `csv:"CreatedAt"` } func main() { csvData := []byte(`name,age,CreatedAt jacek,26,2012-04-01T15:00:00Z john,,0001-01-01T00:00:00Z`) var users []User if err := csvutil.Unmarshal(csvData, &users); err != nil { fmt.Println("error:", err) return } for _, u := range users { fmt.Printf("%+v\n", u) } // Output: // {Name:jacek Age:26 CreatedAt:2012-04-01 15:00:00 +0000 UTC} // {Name:john Age:0 CreatedAt:0001-01-01 00:00:00 +0000 UTC} } ``` -------------------------------- ### Decode CSV with extra metadata using Decoder.Unused in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md This snippet shows how to capture CSV columns that are not mapped to struct fields by using Decoder.Unused. It builds a map of additional data for each record, preserving all information from the source file. Useful when the CSV schema may vary between files. ```go type User struct { Name string `csv:"name"` City string `csv:"city"` Age int `csv:"age"` OtherData map[string]string `csv:"-"` } csvReader := csv.NewReader(strings.NewReader(` name,age,city,zip alice,25,la,90005 bob,30,ny,10005`)) dec, err := csvutil.NewDecoder(csvReader) if err != nil { log.Fatal(err) } header := dec.Header() var users []User for { u := User{OtherData: make(map[string]string)} if err := dec.Decode(&u); err == io.EOF { break } else if err != nil { log.Fatal(err) } for _, i := range dec.Unused() { u.OtherData[header[i]] = dec.Record()[i] } users = append(users, u) } fmt.Println(users) // Output: // [{alice la 25 map[zip:90005]} {bob ny 30 map[zip:10005]}] ``` -------------------------------- ### Normalize CSV data with Decoder.Map to handle NaN values in Go Source: https://github.com/jszwec/csvutil/blob/master/README.md This snippet defines a custom Map function for the Decoder to replace 'n/a' strings with 'NaN' before parsing float fields, preventing parsing errors. It demonstrates how to inspect the target field type and conditionally transform values during decoding. Useful for cleaning inconsistent numeric data. ```go dec, err := csvutil.NewDecoder(r) if err != nil { log.Fatal(err) } dec.Map = func(field, column string, v any) string { if _, ok := v.(float64); ok && field == "n/a" { return "NaN" } return field } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.