Examples in Go
Command-line arguments are a common way to parameterize execution of programs.
package main

import (
    "fmt"
    "os"
)

func main() {

    // os.Args provides access to raw command-line arguments.
    // Note that the first value in this slice is the path to the program,
    // and os.Args[1:] holds the arguments to the program.
    argsWithProg := os.Args
    argsWithoutProg := os.Args[1:]

    // You can get individual args with normal indexing.
    arg := os.Args[3]

    fmt.Println(argsWithProg)
    fmt.Println(argsWithoutProg)
    fmt.Println(arg)
}
Go provides a flag package supporting basic command-line flag parsing. We’ll use this package to implement our example command-line program.
package main

import (
    "flag"
    "fmt"
)

func main() {

    // Basic flag declarations are available for string, integer, and boolean options.
    // Here we declare a string flag word with a default value "foo" and a short description.
    // This flag.String function returns a string pointer (not a string value);
    // we’ll see how to use this pointer below.
    wordPtr := flag.String("word", "foo", "a string")

    // This declares numb and fork flags, using a similar approach to the word flag.
    numbPtr := flag.Int("numb", 42, "an int")
    boolPtr := flag.Bool("fork", false, "a bool")

    // It’s also possible to declare an option that uses an existing var declared elsewhere in the program.
    // Note that we need to pass in a pointer to the flag declaration function.
    var svar string
    flag.StringVar(&svar, "svar", "bar", "a string var")

    // Once all flags are declared, call flag.Parse() to execute the command-line parsing.
    flag.Parse()

    fmt.Println("word:", *wordPtr)
    fmt.Println("numb:", *numbPtr)
    fmt.Println("fork:", *boolPtr)
    fmt.Println("svar:", svar)
    fmt.Println("tail:", flag.Args())
}
Last Run  :
word: foo
numb: 42
fork: false
svar: bar
tail: []
The flag package lets us easily define simple subcommands that have their own flags.
package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {

    // We declare a subcommand using the NewFlagSet function,
    // and proceed to define new flags specific for this subcommand.
    fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
    fooEnable := fooCmd.Bool("enable", false, "enable")
    fooName := fooCmd.String("name", "", "name")

    // For a different subcommand we can define different supported flags.
    barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
    barLevel := barCmd.Int("level", 0, "level")

    if len(os.Args) < 2 {
        fmt.Println("expected 'foo' or 'bar' subcommands")
        os.Exit(1)
    }

    switch os.Args[1] {

    // For every subcommand, we parse its own flags and have access to trailing positional arguments.
    case "foo":
        fooCmd.Parse(os.Args[2:])
        fmt.Println("subcommand 'foo'")
        fmt.Println("  enable:", *fooEnable)
        fmt.Println("  name:", *fooName)
        fmt.Println("  tail:", fooCmd.Args())
    case "bar":
        barCmd.Parse(os.Args[2:])
        fmt.Println("subcommand 'bar'")
        fmt.Println("  level:", *barLevel)
        fmt.Println("  tail:", barCmd.Args())
    default:
        fmt.Println("expected 'foo' or 'bar' subcommands")
        os.Exit(1)
    }
}
package main

import (
    "os"
)

func main() {

    os.Setenv("FOO", "1")
}
package main

import (
    "fmt"
    "os"
)

func main() {

    fmt.Println("FOO:", os.Getenv("FOO"))
}
package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
  
    // Use os.Environ to list all key/value pairs in the environment.
    // This returns a slice of strings in the form KEY=value.
    // You can strings.SplitN them to get the key and value. Here we print all the keys.
    for _, e := range os.Environ() {
        pair := strings.SplitN(e, "=", 2)
        fmt.Println(pair[0])
    }
}
package main

import (
    "fmt"
    "io/ioutil"
    "os/exec"
)

func main() {

    // We’ll start with a simple command that takes no arguments or input and just prints something to stdout.
    // The exec.Command helper creates an object to represent this external process.
    dateCmd := exec.Command("date")

    // .Output is another helper that handles the common case of running a command, waiting for it to finish, and collecting its output.
    // If there were no errors, dateOut will hold bytes with the date info.
    dateOut, err := dateCmd.Output()
    if err != nil {
        panic(err)
    }
    fmt.Println("> date")
    fmt.Println(string(dateOut))

    // Next we’ll look at a slightly more involved case where we pipe data to the external process
    // on its stdin and collect the results from its stdout.
    grepCmd := exec.Command("grep", "hello")

    // Here we explicitly grab input/output pipes, start the process, write some input to it,
    // read the resulting output, and finally wait for the process to exit.
    grepIn, _ := grepCmd.StdinPipe()
    grepOut, _ := grepCmd.StdoutPipe()
    grepCmd.Start()
    grepIn.Write([]byte("hello grep\ngoodbye grep"))
    grepIn.Close()
    grepBytes, _ := ioutil.ReadAll(grepOut)
    grepCmd.Wait()

    fmt.Println("> grep hello")
    fmt.Println(string(grepBytes))

    // Note that when spawning commands we need to provide an explicitly delineated command and argument array, vs. being able to just pass in one command-line string.
    // If you want to spawn a full command with a string, you can use bash’s -c option:
    lsCmd := exec.Command("bash", "-c", "ls -a -l -h")
    lsOut, err := lsCmd.Output()
    if err != nil {
        panic(err)
    }
    fmt.Println("> ls -a -l -h")
    fmt.Println(string(lsOut))
}
Calling exec completely replaces the current Go process with another (perhaps non-Go) one.
package main

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

func main() {

    // For our example we’ll exec ls. Go requires an absolute path to the binary we want to execute,
    // so we’ll use exec.LookPath to find it (probably /bin/ls).
    binary, lookErr := exec.LookPath("ls")
    if lookErr != nil {
        panic(lookErr)
    }

    // Exec requires arguments in slice form (as apposed to one big string).
    // We’ll give ls a few common arguments.
    // Note that the first argument should be the program name.
    args := []string{"ls", "-a", "-l", "-h"}

    // Exec also needs a set of environment variables to use.
    // Here we just provide our current environment.
    env := os.Environ()

    // 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 /bin/ls -a -l -h process.
    // If there is an error we’ll get a return value.
    execErr := syscall.Exec(binary, args, env)
    if execErr != nil {
        panic(execErr)
    }
}
Last Run  :
total 12K
drwx------ 2 runner runner 4.0K Aug 24 17:09 .
drwxrwxrwt 1 root   root   4.0K Aug 24 17:09 ..
-rw-r--r-- 1 runner runner 1.1K Aug 24 17:09 main.go
package main

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

func main() {

    // Go signal notification works by sending os.Signal values on a channel.
    // We’ll create a channel to receive these notifications (we’ll also make one to notify us when the program can exit).
    sigs := make(chan os.Signal, 1)
    done := make(chan bool, 1)

    // signal.Notify registers the given channel to receive notifications of the specified signals.
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

    // This goroutine executes a blocking receive for signals.
    // When it gets one it’ll print it out and then notify the program that it can finish.
    go func() {
        sig := <-sigs
        fmt.Println()
        fmt.Println(sig)
        done <- true
    }()

    fmt.Println("awaiting signal")
    <-done
    fmt.Println("exiting")
}
Use os.Exit to immediately exit with a given status.
package main

import (
    "fmt"
    "os"
)

func main() {

    // defers will not be run when using os.Exit, so this fmt.Println will never be called.
    defer fmt.Println("!")

    os.Exit(3)
}