英文:
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()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论