Golang中如何处理CSV读取时单值上下文的多值问题
Golang中如何处理CSV读取时单值上下文的多值问题
尝试从CSV文件中读取date和number,因此我定义了以下结构体:
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
}
并按以下方式进行读取:
func main() {
// 读取CSV文件线程 > 开始 //
pairs := []Pair{{"m", 1}, {"d", 0}, {"c", 2}}
fmt.Println(pairs)
// 按键排序
sort.Sort(ByKey(pairs))
fmt.Println(pairs)
pairs = append(pairs, Pair{"h", 5})
fmt.Println(pairs)
// 读取CSV文件线程 > 开始 //
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]), // 单值上下文中的多值错误
Quantity: (strconv.ParseFloat(row[5], 64) * 1000).(uint64), // 单值上下文中的多值错误
})
}
peopleJson, _ := json.Marshal(trx.lines)
fmt.Println(string(peopleJson))
input <- trx // 将数据发送到通道读取
}("trx.csv")
<-input // 从通道'read'接收并赋值给新的数据变量
// 读取CSV文件线程 < 结束 //
}
然后遇到了两个错误:
.\pair.go:73:24: multiple-value time.Parse() in single-value context
.\pair.go:74:34: multiple-value strconv.ParseFloat() in single-value context
我理解原因,time.Parse()和strconv.ParseFloat()都返回两个输出:值和错误。可以通过以下方式解决这个问题:
date, _ := time.Parse("%Y-%m-%d", row[4])
// 然后:
Date: date,
但我想知道是否可以避免这样做,并在同一个命令块中解决:
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: ...
}
更多关于Golang中如何处理CSV读取时单值上下文的多值问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
for _, row := range rows[1:] {
date, err := time.Parse("2006-01-02", row[4])
failOnError(err)
f, err := strconv.ParseFloat(row[5], 64)
failOnError(err)
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: date,
Quantity: (f * 1000).(uint64),
})
}
我会这样做。另一种方法是创建一个闭包:
parseDate := func(v string) time.Time {
t, err := time.Parse("2006-01-02", v)
failOnError(err)
return t
}
// ...
Date: parseDate(row[4])
// ...
更多关于Golang中如何处理CSV读取时单值上下文的多值问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,当函数返回多个值时,不能直接在结构体字面量中使用这些函数。不过,你可以通过以下几种方式在同一个代码块中处理:
方案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: func() time.Time {
t, _ := time.Parse("2006-01-02", row[4])
return t
}(),
Quantity: func() uint64 {
f, _ := strconv.ParseFloat(row[5], 64)
return uint64(f * 1000)
}(),
})
方案2:使用辅助函数
func parseDate(s string) time.Time {
t, _ := time.Parse("2006-01-02", s)
return t
}
func parseQuantity(s string) uint64 {
f, _ := strconv.ParseFloat(s, 64)
return uint64(f * 1000)
}
// 在循环中使用
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: parseDate(row[4]),
Quantity: parseQuantity(row[5]),
})
方案3:使用闭包变量(在同一作用域内)
trx.lines = append(trx.lines, func() Transaction {
date, _ := time.Parse("2006-01-02", row[4])
quantity, _ := strconv.ParseFloat(row[5], 64)
return Transaction{
Warehouse: strings.TrimSpace(row[0]),
Item: strings.TrimSpace(row[1]),
Movement: strings.TrimSpace(row[2]),
Batch: strings.TrimSpace(row[3]),
Date: date,
Quantity: uint64(quantity * 1000),
}
}())
方案4:使用结构体方法(推荐)
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 NewTransactionFromCSV(row []string) Transaction {
date, _ := time.Parse("2006-01-02", row[4])
quantity, _ := strconv.ParseFloat(row[5], 64)
return Transaction{
Warehouse: strings.TrimSpace(row[0]),
Item: strings.TrimSpace(row[1]),
Movement: strings.TrimSpace(row[2]),
Batch: strings.TrimSpace(row[3]),
Date: date,
Quantity: uint64(quantity * 1000),
}
}
// 在循环中使用
trx.lines = append(trx.lines, NewTransactionFromCSV(row))
方案5:使用错误处理(完整版本)
func NewTransactionFromCSV(row []string) (Transaction, error) {
date, err := time.Parse("2006-01-02", row[4])
if err != nil {
return Transaction{}, fmt.Errorf("parse date: %w", err)
}
quantity, err := strconv.ParseFloat(row[5], 64)
if err != nil {
return Transaction{}, fmt.Errorf("parse quantity: %w", err)
}
return Transaction{
Warehouse: strings.TrimSpace(row[0]),
Item: strings.TrimSpace(row[1]),
Movement: strings.TrimSpace(row[2]),
Batch: strings.TrimSpace(row[3]),
Date: date,
Quantity: uint64(quantity * 1000),
}, nil
}
// 在循环中使用
transaction, err := NewTransactionFromCSV(row)
if err != nil {
// 处理错误
continue
}
trx.lines = append(trx.lines, transaction)
注意:你的代码中时间格式字符串有误,应该是 "2006-01-02" 而不是 "%Y-%m-%d",这是Go语言特定的时间格式。

