Golang:管理后台操作(创建/杀死)

问题描述 投票:-1回答:1

我第一次在这里发布是因为我在互联网上找不到干净的解决方案。

我的目标很简单,我需要创建一个后台操作(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。

谢谢你。

go concurrency kill
1个回答
0
投票

您的问题在这里:

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中的
  • 函数
  • returns
  • ,所以将其放入循环中毫无意义-在这种情况下,此代码无法ever执行循环的第二次迭代
    © www.soinside.com 2019 - 2024. All rights reserved.