我大概想写一个按行读取文件送到channel里,另一个从channel中取出处理的程序。遇到了一些问题:
ok <- nil
通知,这里我就觉得很不优雅,两个channel都是作为参数传进来的,没有用上返回值。我不知道怎么修改。package main
import (
"bufio"
"fmt"
"os"
)
func main() {
err := program()
if err != nil {
panic(err)
}
}
func program() error {
f, err := os.Open("data.txt")
if err != nil {
return err
}
defer f.Close()
scanner := bufio.NewScanner(f)
ch := make(chan string, 3)
ok := make(chan any)
ok2 := make(chan any)
go reader(scanner, ch, ok)
go outputer(ch, ok2)
<-ok
if err := scanner.Err(); err != nil {
return err
}
close(ch)
<-ok2
fmt.Println(len(ch))
fmt.Println("完成")
return nil
}
func reader(scanner *bufio.Scanner, data chan string, ok chan any) {
for scanner.Scan() {
data <- scanner.Text()
}
ok <- nil
}
func outputer(data chan string, ok chan any) {
for s := range data {
go func(s string) {
fmt.Println(s)
}(s)
}
ok <- nil
}
3.没办法调试。我用的是VSCode,会报错invalid command
4.程序的所有方面的结构,如果各位有改进建议,还请不吝赐教。
1.该加sleep加sleep,执行太快你根本分辨不出来谁先执行谁后执行的,该加同步锁加同步锁,避免线程不安全
2.打印了完成并不是真的完成,因为子线程没有完,但主线程已经执行完了,此时先打印了完成,但子线程还在执行
你可以在启动子线程之后执行线程同步,必须线程执行完毕再继续执行主线程
也可以在子线程里判断数据全都处理完了再打印完成,而不是启动了线程就直接打印完成
3.多线程是没办法断点跟踪的,这在哪个语言都一样,你需要一些特别的调试技巧
1、使用布尔类型的信号量通知读取完毕,代替"ok <- nil"的方式:
func reader(scanner *bufio.Scanner, data chan string, done chan bool) {
for scanner.Scan() {
data <- scanner.Text()
}
close(data)
done <- true
}
func outputer(data chan string, done chan bool) {
for s := range data {
fmt.Println(s)
}
done <- true
}
func program() error {
f, err := os.Open("data.txt")
if err != nil {
return err
}
defer f.Close()
scanner := bufio.NewScanner(f)
ch := make(chan string, 3)
done1 := make(chan bool)
done2 := make(chan bool)
go reader(scanner, ch, done1)
go outputer(ch, done2)
<-done1
if err := scanner.Err(); err != nil {
return err
}
<-done2
fmt.Println("完成")
return nil
}
2、修改"outputer"中的匿名函数为普通函数,提高代码可读性
func processLine(s string) {
fmt.Println(s)
}
func outputer(data chan string, done chan bool) {
for s := range data {
processLine(s)
}
done <- true
}
3、将VSCode的调试设置按照文档指示进行设置
不知道你这个问题是否已经解决, 如果还没有解决的话: