简体   繁体   中英

handling multiple-value in single-value context with csv read

Trying to read date and number from csv file, so I've the below struct

type Transaction struct {
    Warehouse string    `json:"warehouse"`
    Item      string    `json:"item"`
    Movement  string    `json:"movement"`
    Batch     string    `json:"batch"`
    Date      time.Time `json:"transaction_data"`
    Quantity  uint64    `json:"quantity"`
}

type Transactions struct {
    header []string
    lines  []Transaction
}

And do the reading as below:

func main() {
    // Reading csv file thread > START //
    pairs := []Pair{{"m", 1}, {"d", 0}, {"c", 2}}
    fmt.Println(pairs)
    // Sort by Key
    sort.Sort(ByKey(pairs))
    fmt.Println(pairs)
    pairs = append(pairs, Pair{"h", 5})
    fmt.Println(pairs)

    // Reading csv file thread > START //
    input := make(chan Transactions)
    go func(input_file string) {
        var trx Transactions
        fr, err := os.Open(input_file)
        failOnError(err)
        defer fr.Close()
        r := csv.NewReader(fr)
        rows, err := r.ReadAll()
        failOnError(err)
        trx.header = rows[0]
        for _, row := range rows[1:] {
            trx.lines = append(trx.lines, Transaction{
                Warehouse: strings.TrimSpace(row[0]),
                Item:      strings.TrimSpace(row[1]),
                Movement:  strings.TrimSpace(row[2]),
                Batch:     strings.TrimSpace(row[3]),
                Date:      time.Parse("%Y-%m-%d", row[4]),                   // multiple-value in single-value context error
                Quantity:  (strconv.ParseFloat(row[5], 64) * 1000).(uint64),  // multiple-value in single-value context error
            })
        }

        peopleJson, _ := json.Marshal(trx.lines)
        fmt.Println(string(peopleJson)) 

        input <- trx // send data to channel read
    }("trx.csv")
    <-input // rceive from channel 'read' and assign value to new data variable
    // Reading csv file thread < END //
}

And got 2 errors:

.\pair.go:73:24: multiple-value time.Parse() in single-value context
.\pair.go:74:34: multiple-value strconv.ParseFloat() in single-value context

I understand the reason, which is both time.Parse() and strconv.ParseFloat() returning 2 outputs, value and error, and can overcome this issue by writing:

date, _ := time.Parse("%Y-%m-%d", row[4])
// and later:
Date:      date,

But I'm wondering if I can avoid this, and get it resolved within the same command block:

trx.lines = append(trx.lines, Transaction{
                Warehouse: strings.TrimSpace(row[0]),
                Item:      strings.TrimSpace(row[1]),
                Movement:  strings.TrimSpace(row[2]),
                Batch:     strings.TrimSpace(row[3]),
                Date:      ...
                Quantity:  ...
}

I got the answer (thanks for the productive comments, only the productive one)

Solution making a separate function that read the 2 context, and return the value only as below:

func mustTime(t time.Time, err error) time.Time { failOnError(err); return t }
func mustNumber(d float64, err error) uint64    { failOnError(err); return uint64(d + 1000) }

Then calling it as:

Date:      mustTime(time.Parse("%Y-%m-%d", row[4])),
Quantity:  mustNumber(strconv.ParseFloat(row[5], 64)),

So, full correct code became:

package main

import (
    "encoding/csv"
    "encoding/json"
    "fmt"
    "log"
    "os"
    "sort"
    "strconv"
    "strings"
    "time"
)

func failOnError(err error) {
    if err != nil {
        log.Fatal("Error:", err)
        panic(err)
    }
}

type Pair struct {
    Key   string
    Value float64
}

type ByKey []Pair

func (s ByKey) Len() int {
    return len(s)
}

func (s ByKey) Swap(i, j int) {
    s[i], s[j] = s[j], s[i]
}

func (s ByKey) Less(i, j int) bool {
    return s[i].Key < s[j].Key
}

func (s ByKey) pop() bool {
    //s = append(s,[0 : s.Len()-1])
    return true
}

func main() {
    // Reading csv file thread > START //
    pairs := []Pair{{"m", 1}, {"d", 0}, {"c", 2}}
    fmt.Println(pairs)
    // Sort by Key
    sort.Sort(ByKey(pairs))
    fmt.Println(pairs)
    pairs = append(pairs, Pair{"h", 5})
    fmt.Println(pairs)

    // Reading csv file thread > START //
    input := make(chan Transactions)
    go func(input_file string) {
        var trx Transactions
        fr, err := os.Open(input_file)
        failOnError(err)
        defer fr.Close()
        r := csv.NewReader(fr)
        rows, err := r.ReadAll()
        failOnError(err)
        trx.header = rows[0]
        for _, row := range rows[1:] {
            trx.lines = append(trx.lines, Transaction{
                Warehouse: strings.TrimSpace(row[0]),
                Item:      strings.TrimSpace(row[1]),
                Movement:  strings.TrimSpace(row[2]),
                Batch:     strings.TrimSpace(row[3]),
                Date:      mustTime(time.Parse("%Y-%m-%d", row[4])),
                Quantity:  mustNumber(strconv.ParseFloat(row[5], 64)),
            })
        }

        peopleJson, _ := json.Marshal(trx.lines)
        fmt.Println(string(peopleJson)) // This is working smoothly

        input <- trx // send data to channel read
    }("trx.csv")
    //data :=
    <-input // rceive from channel 'read' and assign value to new data variable
    // Reading csv file thread < END //
}

type Transactions struct {
    header []string
    lines  []Transaction
}

type Transaction struct {
    Warehouse string    `json:"warehouse"`
    Item      string    `json:"item"`
    Movement  string    `json:"movement"`
    Batch     string    `json:"batch"`
    Date      time.Time `json:"transaction_data"`
    Quantity  uint64    `json:"quantity"`
}

func mustTime(t time.Time, err error) time.Time { failOnError(err); return t }
func mustNumber(d float64, err error) uint64    { failOnError(err); return uint64(d + 1000) }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM