下面是完整的源代码,你可以查看这个仓库(https:/ /gitlab.com/sj14/gosh/),但源代码有可能已经与本文中展示的代码有所不同。

package main

import (

    "bufio"

    "errors"

    "fmt"

    "os"

    "os/exec"

    "strings"

)


func main() {

    reader := bufio.NewReader(os.Stdin)

    for {

        fmt.Print("> ")

        // Read the keyboad input.

        input, err := reader.ReadString('\n')

        if err != nil {

            fmt.Fprintln(os.Stderr, err)

        }


        // Handle the execution of the input.

        err = execInput(input)

        if err != nil {

            fmt.Fprintln(os.Stderr, err)

        }

    }

}


// ErrNoPath is returned when 'cd' was called without a second argument.

var ErrNoPath = errors.New("path required")


func execInput(input string) error {

    // Remove the newline character.

    input = strings.TrimSuffix(input, "\n")


    // Split the input separate the command and the arguments.

    args := strings.Split(input, " ")


    // Check for built-in commands.

    switch args[0] {

        case "cd":

            // 'cd' to home with empty path not yet supported.

            if len(args) < 2 {

                return ErrNoPath

            }

            err := os.Chdir(args[1])

            if err != nil {

                return err

            }

            // Stop further processing.

            return nil

        case "exit":

            os.Exit(0)

    }

    // Prepare the command to execute.

    cmd := exec.Command(args[0], args[1:]...)


    // Set the correct output device.

    cmd.Stderr = os.Stderr

    cmd.Stdout = os.Stdout


    // Execute the command and save it's output.

    err := cmd.Run()

    if err != nil {

        return err

    }

    return nil

}