英文:
should I use a channel or a sync.Mutex lock()?
问题
在执行go test -race时,我发现在命令开始之前就调用了os.Process.Kill,我提出了两种可能的解决方案,一种是使用channel:
package main
import "os/exec"
func main() {
    cmd := exec.Command("sleep", "10")
    started := make(chan struct{}, 1)
    go func() {
        <-started
        cmd.Process.Kill()
    }()
    if err := cmd.Start(); err != nil {
        panic(err)
    }
    started <- struct{}{}
    cmd.Wait()
}
另一种是使用lock:
package main
import (
    "os/exec"
    "sync"
)
func main() {
    var lock sync.Mutex
    cmd := exec.Command("sleep", "10")
    lock.Lock()
    if err := cmd.Start(); err != nil {
        panic(err)
    }
    lock.Unlock()
    go func() {
        cmd.Process.Kill()
    }()
    cmd.Wait()
}
这两种方法都可以工作,但想知道哪种方法更符合惯用方式或更好,主要目标是防止杀死尚未启动的进程。
英文:
While doing a go test -race, I found that a call to os.Process.Kill, was made before the  command started cmd.Start(), I came with to posible solutions, one to use a channel:
package main
import "os/exec"
func main() {
	cmd := exec.Command("sleep", "10")
	started := make(chan struct{}, 1)
	go func() {
		<-started
		cmd.Process.Kill()
	}()
	if err := cmd.Start(); err != nil {
		panic(err)
	}
	started <- struct{}{}
	cmd.Wait()
}
or to use a lock:
package main
import (
    "os/exec"
    "sync"
)
func main() {
	var lock sync.Mutex
	cmd := exec.Command("sleep", "10")
	lock.Lock()
	if err := cmd.Start(); err != nil {
		panic(err)
	}
	lock.Unlock()
	go func() {
		cmd.Process.Kill()
	}()
	cmd.Wait()
}
Both options work but wondering what could be the most idiomatic or better approach, while the main goal is just to prevent killing a process that hasn't been started.
答案1
得分: 0
我建议你使用一个通道,但是让我指出一些关于你的代码的问题。
我注意到你使用了一个带缓冲的通道,并且在调用消费通道的 goroutine 之前先向该通道发送数据。在我看来,以下做法可能更好:
1)在这种情况下,使用一个无缓冲的通道进行信号传递会更好。
2)让 goroutine 负责启动进程并调用等待函数,同时向主函数发出已启动的信号。
代码示例如下:
package main
import "os/exec"
func main() {
    cmd := exec.Command("sleep", "10")
    started := make(chan struct{})
    go func(cmd *exec.Cmd, signal chan struct{}) {
        if err := cmd.Start(); err != nil {
            panic(err)
        }
        
        started <- struct{}{}
        cmd.Wait()
    }(cmd, started)
    
    <-started
    cmd.Process.Kill()
}
以上是翻译好的内容,请确认是否满意。
英文:
I would suggest you use a channel, but let me point out something about your code.
I noticed you used a buffered channel, and then sent data on that channel first, before calling the goroutine that consumes the channel. In my opinion, it would be better to:
- 
use an unbuffered channel for signalling, especially in this case.
 - 
Have the goroutine be responsible for starting the process and calling wait, while signaling to the main that it has started.
 
Like this:
package main
import "os/exec"
func main() {
    cmd := exec.Command("sleep", "10")
    started := make(chan struct{})
    go func(cmd *exec.Cmd, signal chan struct{}) {
        if err := cmd.Start(); err != nil {
            panic(err)
        }
        
        started <- struct{}{}
        cmd.Wait()
    }(cmd, started)
    
    <-started
    cmd.Process.Kill()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论