1 回答

TA贡献1813条经验 获得超2个赞
问题是这样的:
select {
case data := <-read:
go func(data Data) {
这select是main函数中的最后一件事。当它从 读取data时read,它会在后台启动一个 goroutine 来处理它。然后main函数结束,程序退出。
Go 不会自动等待 goroutines。您可以使用“完成”通道或其他任何方式在它们之间进行同步。
你基本上有一个在概念上看起来像这样的管道:
----> process -> write to `out`
/
start --> main file waits data on `read` *or* wait for `out` -> done
\
---> CSV reads all lines and outputs data to `read`
因为您实际上只通过频道发送一条消息,所以您实际上并不需要 aselect或 a loop。你只需要等待数据,处理它,然后main等待完成:
package main
import (
"encoding/csv"
"encoding/json"
"fmt"
"log"
"os"
)
func failOnError(err error) {
if err != nil {
log.Fatal("Error:", err)
panic(err)
}
}
func main() {
read := make(chan Data)
go func(input_file string) {
var data Data
fr, err := os.Open(input_file)
failOnError(err)
defer fr.Close()
r := csv.NewReader(fr)
rows, err := r.ReadAll()
failOnError(err)
data.header = rows[0]
for _, row := range rows[1:] {
data.lines = append(data.lines, Person{
Firstname: row[0],
Lastname: row[1],
Address: &Address{
City: row[2],
State: row[3],
},
})
}
peopleJson, _ := json.Marshal(data.lines)
fmt.Println(string(peopleJson)) // This is working smoothly
read <- data
}("people.csv")
csvOut, err := os.Create("resultsfile.csv")
if err != nil {
log.Fatal("Unable to open output")
}
out := make(chan int)
go func() {
data := <-read
println("data received") // <-- Not show up
w := csv.NewWriter(csvOut)
defer csvOut.Close()
// handle header
data.header = append(data.header, "score")
if err = w.Write(data.header); err != nil {
log.Fatal(err)
}
/*
hanlde data
*/
w.Flush()
out <- 0
}()
<-out
println("done")
}
type Person struct {
Firstname string `json:"firstname"` // JSON annotation will allow for easy printing to JSON after it had been loaded
Lastname string `json:"lastname"`
Address *Address `json:"address,omitempty"`
}
type Address struct {
City string `json:"city"`
State string `json:"state"`
}
type Data struct {
header []string
lines []Person
}
OP问,
有没有办法在没有选择的情况下从以前的频道接收输入,同时确保程序在完成所需内容之前不退出?– Hasan A Yousef 1 分钟前
您所写的所有频道都只传递一条消息,这意味着一旦您阅读了该频道一次,您就可以假设作者是完整的。因此,通过使用out渠道,您已经实现了这一点。
如果您有未知数量的发送到通道,您可以使用内置close功能来实现此目的:
package main
import (
"fmt"
)
func main() {
send := make(chan int)
result := make(chan int)
go func() {
sum := 0
for i := range send {
sum += i
}
result <- sum
}()
for _, x := range []int{1,2,3} {
send <- x
}
close(send)
fmt.Println("Sum is: ", <-result)
}
- 1 回答
- 0 关注
- 123 浏览
添加回答
举报