TTuck

In the previous example we looked at spawning external processes. We do this when we need an external process accessible to a running Go process. Sometimes we just want to completely replace the current Go process with another (perhaps non-Go) one. To do this we'll use Go's implementation of the classic exec function.

package main

import (
	"fmt"
	"os"
	"os/exec"
	"syscall"
)

func main() {

For our example we'll exec echo. Go requires an absolute path to the binary we want to execute, so we'll use exec.LookPath to find it.

	binary, lookErr := exec.LookPath("echo")
	if lookErr != nil {
		panic(lookErr)
	}

Exec requires arguments in slice form (as opposed to one big string). By convention, the first argument should be the program name.

	args := []string{"echo", "this", "process", "is", "now", "echo"}

Exec also needs a set of environment variables to use. Here we just provide our current environment.

	env := os.Environ()

	fmt.Println("about to exec", len(args)-1, "arguments")

Here's the actual syscall.Exec call. If this call is successful, the execution of our process will end here and be replaced by the echo process. If there is an error we'll get a return value.

	execErr := syscall.Exec(binary, args, env)
	if execErr != nil {
		panic(execErr)
	}

Note that Go does not offer a classic Unix fork function. Usually this isn't an issue though, since starting goroutines, spawning processes, and exec'ing processes covers most use cases for fork.

	fmt.Println("never printed")
}
$ go run ./86_execing_processes
about to exec 5 arguments
this process is now echo