-3

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:  ...
}
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203
  • 1
    Possible duplicate of [Multiple values in single-value context](https://stackoverflow.com/questions/28227095/multiple-values-in-single-value-context/28233172#28233172). – icza Jun 03 '20 at 16:24
  • 2
    Discarding errors is almost never the solution, but you've got the gist of it. The general solution is to do exactly as you have in the question, handle those before the struct literal. The alternative is as @BlahBlahBlah said, make yourself a wrapper function that handles the error in some way (panic, log, whatever) and just returns the value. But if you *don't* panic, be prepared to have bogus values in your data since you're using them whether or not the parse succeeded. – Adrian Jun 03 '20 at 16:24
  • @icza it is not duplicate, you can read both and check – Hasan A Yousef Jun 03 '20 at 16:36

1 Answers1

0

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) }
Hasan A Yousef
  • 22,789
  • 24
  • 132
  • 203