Go语言循环读取STDIN并阻塞:父子进程管道交互异常求助
问题分析与解决方案
你的核心问题是子进程在首次读取STDIN后,后续读取持续返回EOF导致无限循环,结合代码和场景来看,主要原因有两点:一是输入读取方式不匹配行读取需求,二是遇到EOF时未正确终止循环,同时父进程的管道写端处理也可能存在问题。
问题拆解
fmt.Scan(&line)的局限性:该方法会跳过前导空白,且仅读取到下一个空白字符(空格、换行等)为止,无法完整读取整行输入,尤其不适合父进程按行发送数据的场景。- EOF处理逻辑缺失:当父进程关闭管道写端后,子进程的STDIN会持续返回EOF,但你的代码仅打印错误却不终止循环,导致无限重复读取EOF。
- 父进程管道维护问题:如果父进程写完一次数据就关闭管道写端,子进程的STDIN会直接进入EOF状态,无法接收后续输入。
修复后的子进程代码
推荐使用bufio.Scanner实现可靠的行读取和阻塞等待,它会自动处理阻塞和EOF逻辑:
package main import ( "bufio" "log" "os" ) func main() { scanner := bufio.NewScanner(os.Stdin) // 循环阻塞读取STDIN,直到EOF或收到停止命令 for scanner.Scan() { line := scanner.Text() if line == "stop" { break } // 这里添加你的业务逻辑,比如处理输入并输出到STDOUT log.Printf("收到输入: %s", line) } // 检查扫描过程中的异常错误(EOF不属于错误) if err := scanner.Err(); err != nil { log.Fatalf("读取STDIN失败: %v", err) } log.Println("程序正常退出") }
如果你更倾向于使用bufio.Reader,可以这样实现:
package main import ( "bufio" "io" "log" "os" "strings" ) func main() { reader := bufio.NewReader(os.Stdin) for { line, err := reader.ReadString('\n') if err != nil { if err == io.EOF { // 父进程关闭管道写端,正常退出循环 log.Println("STDIN已关闭,退出程序") break } // 其他读取错误直接终止 log.Fatalf("读取失败: %v", err) } // 去掉末尾的换行符 line = strings.TrimSuffix(line, "\n") if line == "stop" { break } log.Printf("收到输入: %s", line) } }
父进程注意事项
父进程需要保持管道写端打开,直到需要停止子进程时再发送stop命令或关闭写端,示例代码(Go语言父进程):
package main import ( "io" "log" "os/exec" ) func main() { cmd := exec.Command("./your-child-process") stdin, err := cmd.StdinPipe() if err != nil { log.Fatal(err) } stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } // 启动子进程 if err := cmd.Start(); err != nil { log.Fatal(err) } // 向子进程发送多行数据 _, err = io.WriteString(stdin, "hello\n") if err != nil { log.Fatal(err) } _, err = io.WriteString(stdin, "world\n") if err != nil { log.Fatal(err) } // 发送停止命令 _, err = io.WriteString(stdin, "stop\n") if err != nil { log.Fatal(err) } stdin.Close() // 关闭写端,子进程处理完后退出 // 读取子进程输出 output, err := io.ReadAll(stdout) if err != nil { log.Fatal(err) } log.Printf("子进程输出: %s", output) // 等待子进程退出 if err := cmd.Wait(); err != nil { log.Fatal(err) } }
内容的提问来源于stack exchange,提问作者user20006944
相关产品推荐
相关产品推荐

