Golang中Listener导致stdin输入和日志记录失效问题
Golang中Listener导致stdin输入和日志记录失效问题 如果我将第19行和第20行注释掉(即不启动监听器),那么日志记录和等待功能都能正常工作。但如果保留这些代码,一旦监听器启动,后续的日志记录就无法进行。"before listener starts"能够正确记录,但"after listener starts"则不会。同时,等待标准输入的功能也无法正常工作。出于测试目的,我希望能够记录各种消息并时不时等待输入。有人知道解决方法吗?
package main
import ("fmt"
"net/http"
"log"
"os"
"bufio")
var mux = http.NewServeMux()
func index(w http.ResponseWriter, r *http.Request) { }
func main() {
mux.HandleFunc("/", index)
logFile, err1 := os.OpenFile("logfile.txt", os.O_RDWR|os.O_CREATE, 0755)
if err1 != nil { fmt.Println("error opening log file")
return }
defer logFile.Close()
log.SetOutput(logFile)
fmt.Println("test log pgm")
log.Println("before listener starts")
err := http.ListenAndServe(":8080", mux) // take this out, and logging works correctly
log.Fatal(err) // and this
log.Println("after listener starts")
wait()
return
}
func wait() {
fmt.Println("waiting...")
log.Println("waiting...")
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
input=input+"dummy"
}
更多关于Golang中Listener导致stdin输入和日志记录失效问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
引用 buzzersdad:
err := http.ListenAndServe(":8080", mux) // 移除此行,日志记录即可正常工作
http.ListenAndServe() 会阻塞执行,因此在它返回错误之前,后续代码都不会被执行。
更多关于Golang中Listener导致stdin输入和日志记录失效问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我通常在请求到达处理程序时立即进行日志记录。
如果你确实想在其后记录日志,可以使用 go 协程,但请注意!
go http.ListenAndServe(…)
fmt.Println("after ListenAndServe")
这里实际的打印可能会在 go 协程获得调度器分配的时间之前发生…
是的,谢谢,但我需要为我的应用程序设置一个监听器。那么当我有活跃的监听器时,就不能进行日志记录了吗?也许有其他的日志记录方式。如果我只是使用 fmt 输出到标准输出,它存储的输出量是有限的,在达到限制后会用更新的内容覆盖较早的内容。从应用程序的许多不同部分写入文件似乎有些过度。
func main() {
fmt.Println("hello world")
}
问题分析:
当调用 http.ListenAndServe() 时,该函数会阻塞并持续监听HTTP请求,这意味着它不会返回(除非发生错误),因此后续的代码(包括日志记录和等待输入)无法执行。log.Fatal() 会在 ListenAndServe 返回错误时记录并退出程序,但正常情况下 ListenAndServe 不会返回。
解决方案:
需要在单独的goroutine中启动HTTP服务器,这样主goroutine可以继续执行后续的日志记录和等待输入功能。
修改后的代码示例:
package main
import (
"bufio"
"fmt"
"log"
"net/http"
"os"
)
var mux = http.NewServeMux()
func index(w http.ResponseWriter, r *http.Request) {}
func main() {
mux.HandleFunc("/", index)
logFile, err1 := os.OpenFile("logfile.txt", os.O_RDWR|os.O_CREATE, 0755)
if err1 != nil {
fmt.Println("error opening log file")
return
}
defer logFile.Close()
log.SetOutput(logFile)
fmt.Println("test log pgm")
log.Println("before listener starts")
// 在goroutine中启动HTTP服务器
go func() {
err := http.ListenAndServe(":8080", mux)
if err != nil {
log.Fatal(err)
}
}()
log.Println("after listener starts")
wait()
}
func wait() {
fmt.Println("waiting...")
log.Println("waiting...")
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
input = input + "dummy"
log.Printf("Received input: %s", input)
}
关键修改:
- 将
http.ListenAndServe()调用包装在goroutine中:go func() { ... }() - 移除了原来的
log.Fatal(err)行,改为在goroutine内部处理错误 - 这样主goroutine可以继续执行到
log.Println("after listener starts")和wait()函数
现在HTTP服务器会在后台运行,同时程序可以正常记录日志并等待用户输入。

