我第一次在这里发布是因为我在互联网上找不到干净的解决方案。
我的目标很简单,我需要创建一个后台操作(goroutine或process或??),可以将其正确杀死(而不留在后台)。
我已经尝试了很多类似使用chan或context的方法。
但是我永远找不到避免泄漏的正确方法。
这里是一个例子:
package main
import (
"log"
"strconv"
"runtime"
"time"
"math/rand"
)
func main() {
log.Println("goroutines: " + strconv.Itoa(runtime.NumGoroutine()))
func1()
leak := ""
if runtime.NumGoroutine() > 1 {
leak = " there is one LEAK !!"
}
log.Println("goroutines: " + strconv.Itoa(runtime.NumGoroutine()) + leak)
}
func func1() {
quit := make(chan struct{})
go func() {
log.Println("goroutines: " + strconv.Itoa(runtime.NumGoroutine()))
for {
select {
case <-quit:
log.Println("USEFUL ???")
return
default:
func2()
quit<-struct{}{}
return
}
}
}()
select {
case <-time.After(4 * time.Second):
close(quit) // useful ???
log.Println("TIMEOUT")
case <-quit:
log.Println("NO TIMEOUT")
}
}
func func2() {
log.Println("JOB START")
rand.Seed(time.Now().UnixNano())
val := rand.Intn(10)
log.Println("JOB DURATION: " + strconv.Itoa(val))
time.Sleep(time.Duration(val) * time.Second) // fake a long process with an unknown duration
log.Println("JOB DONE")
}
在此示例中,如果作业在4秒钟的超时之前完成,那么一切都很好,goroutine的最终数量将为1,否则像我可以找到的每个示例一样,它将为2。
谢谢你。
您的问题在这里:
quit := make(chan struct{})
go func() {
for {
select {
case <-quit:
log.Println("USEFUL ???")
return
default:
func2()
quit<-struct{}{}
return
}
}
}()
此goroutine是unbuffered通道上的signalling本身。这意味着当到达quit<-struct{}{}
时,该发送将永远阻塞,因为它正在等待[[on on]]接收。不过,目前尚不清楚这是如何工作的;这里发生了一些奇怪的事情:一个goroutine正在通过通道发送信号,这似乎是错误的-它不需要进行通信[[与其自身
quit<-struct{}{}
可以替换为log.Println("USEFUL ???")
,并且可以删除整个for / select / channel业务]C0]的每个case
中的