我应该使用通道还是sync.Mutex lock()?

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.

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:

1) use an unbuffered channel for signalling, especially in this case.

2) 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()
}