我现在正在学习 Go,我的第一个项目是一个简单的 ping 脚本。本质上,我想 ping 一堆 url,并在每个响应时等待 XXX 秒,然后再次 ping。这是删减的代码:
func main() {
// read our text file of urls
f, err := ioutil.ReadFile(urlFile)
if err != nil {
log.Print(err)
}
urlStrings := []string{}
urlStrings = strings.Split(string(f), "\n")
for _, v := range urlStrings {
go ping(v)
}
// output logs to the terminal
// channel is global
for i := range c {
fmt.Println(i)
}
}
func ping(url string) {
// for our lag timer
start := time.Now()
// make our request
_, err := http.Get(url)
if err != nil {
msg := url + " Error:" + err.Error()
fmt.Println(msg)
c <- msg
reportError(msg)
} else {
lag := time.Since(start)
var msg string
// running slow
if lag > lagThreshold*time.Second {
msg = url + " lag: " + lag.String()
reportError(msg)
}
msg = url + ", lag: " + lag.String()
c <- msg
}
time.Sleep(pingInterval * time.Second)
go ping(url) // is this acceptable?
}
在我的 Get 请求中,我之前调用了 defer res.Body.Close() ,但在应用程序运行了一段时间后,这令人恐慌。我假设在 goroutine 被垃圾收集并且 res 不再存在之前,defer 无法在响应上调用 Close()。
这让我想到如果在 goroutine 内部调用 goroutine 是最佳实践,或者我是否导致函数永远不会退出,那么只有在 goroutine 被垃圾收集后才会调用 defer。