【发布时间】:2013-04-23 16:16:39
【问题描述】:
我现在正在学习 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 不再存在之前,延迟无法调用响应上的 Close()。
这让我想到,如果在 goroutine 中调用 goroutine 是最佳实践,或者我是否会导致函数永远不会退出,那么只有在 goroutine 被垃圾回收后才会调用 defer。
【问题讨论】:
-
从其他 goroutine 生成 goroutine 应该没有任何问题,但是在这种情况下有什么理由不只使用循环吗?
-
@JamesHenstridge 我没有在程序循环中执行此操作,因此我不必等待每个请求返回,然后再调用下一个请求。我正在尝试使用并发,因此每个 ping 周期都是独立的,基于它自己的延迟时间。
-
我指的是
ping()goroutine 在退出之前生成另一个 goroutine 的部分。如果你在ping()里面放一个循环,你会得到同样的效果。 -
这听起来像是一个更好的解决方案。我会更新我的代码。