Go语言中bufio.ReadString读取到EOF时如何跳出循环执行后续代码
问题根源
你的代码直接终止是三个原因导致的:
- 你定义的
check函数遇到任何错误都会直接panic终止程序,但io.EOF是读取到流结束的正常信号,不属于需要终止程序的异常错误 - 你在进入循环前第一次读取行的时候,就直接调用了
check(err3),如果这时候刚好读到EOF,会直接触发panic,根本走不到后续的循环break逻辑 - 额外的编译问题:你注释了
import "strings",但后续代码用到了strings.Replace,会导致编译不通过
修复方案
- 调整读取逻辑,单独处理EOF错误,只有非EOF的异常错误才调用check终止
- 优化循环结构,避免重复的读取代码
- 恢复strings包的导入
修复后的完整代码
package main import "fmt" import "bufio" import "net" import "os" import "log" import "strings" import "io" func check(e error) { if e != nil { panic(e) } } func main() { fmt.Println("Launching server...") ln, err := net.Listen("tcp", ":12003") check(err) conn, err := ln.Accept() check(err) defer ln.Close() defer conn.Close() //read file size(string) reader1 := bufio.NewReader(conn) m_size, err1 := reader1.ReadString('\n') check(err1) //print file size fmt.Printf("Upload file size: %s", m_size) //create new file out_file := "whatever.txt" newfile, err2 := os.Create(out_file) check(err2) defer newfile.Close() //read and write line to new file writer1 := bufio.NewWriter(newfile) var i = 1 for { line, err3 := reader1.ReadString('\n') // 先处理读到的内容,再处理错误 if line != "" { writer1.WriteString(fmt.Sprintf("%d %s", i, line)) i++ } // 错误判断 if err3 != nil { if err3 == io.EOF { // 正常结束,跳出循环 break } // 其他异常错误才终止 check(err3) } } writer1.Flush() // get the new file's size and print stats, errr := os.Stat(out_file) if errr != nil { log.Fatal(errr) } fmt.Printf("Output file size: %d\n", stats.Size()) // send message back to client writer2 := bufio.NewWriter(conn) m_size = strings.Replace(m_size, "\n", "", -1) newline := fmt.Sprintf("%s bytes received, %d bytes file generated", m_size, stats.Size()) _, errw := writer2.WriteString(newline) check(errw) writer2.Flush() }
关键修改说明
- 新增导入
io包,用来判断io.EOF错误 - 把循环外的第一次读取逻辑整合到
for循环内部,避免重复代码 - 读取到内容后先写入文件,再判断错误:因为
ReadString在遇到EOF的时候,可能同时返回已经读到的未结束的行内容,所以要先处理内容再处理错误 - 单独判断EOF错误,遇到EOF直接跳出循环继续执行后续代码,只有非EOF的异常错误才调用check终止程序
- 恢复了
strings包的导入,解决编译错误
内容的提问来源于stack exchange,提问作者Karen0104
相关产品推荐
相关产品推荐

