Help us shape the future of Go! Take the 2026 Go Developer Survey

gocmd

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package gocmd runs the go command.

Runner is the seam: ExecRunner runs the real binary, WithTimeout bounds any runner, and tests substitute a fake. A Runner returns an error only when go could not be run at all; a non-zero exit is reported in Result.Code.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("go not installed")

ErrNotFound reports that the go command is not installed.

Functions

func SignalCause

func SignalCause(sig os.Signal) error

SignalCause is the cause to cancel a context with (context.WithCancelCause) when sig ended the run. A process started on that context is then sent sig, not SIGTERM, and SignalOf tells which signal it was.

func SignalOf

func SignalOf(ctx context.Context) (os.Signal, bool)

SignalOf is the signal that cancelled ctx, when it was cancelled with SignalCause.

Types

type Call

type Call struct {
	Dir  string   // child working directory
	Env  []string // KEY=VALUE pairs overriding the process environment
	Args []string // arguments after "go"
}

Call is one invocation of the go command. The process working directory is never changed; Dir is applied to the child only.

type ExecProcessRunner

type ExecProcessRunner struct{}

ExecProcessRunner runs the real program. The child stays in gotools' process group, so the terminal delivers Ctrl-C to it directly and it may read the terminal; cancelling the context sends it SIGTERM, and it is killed if it does not stop. If the context was cancelled with SignalCause, the child gets that signal, else SIGTERM.

func (ExecProcessRunner) Run

Run implements ProcessRunner.

type ExecRunner

type ExecRunner struct {
	Bin     string    // defaults to "go" from PATH
	Verbose io.Writer // when set, "  ↳ go <args>" is written before each call
	// Env is KEY=VALUE pairs added to the environment of every call; a call's
	// own Env still wins over it.
	Env []string
}

ExecRunner runs the real go binary with stdin empty. The child gets its own process group, so cancelling stops the compiler and linker go spawns too.

func (ExecRunner) Run

func (g ExecRunner) Run(ctx context.Context, c Call) (Result, error)

Run implements Runner.

type Process

type Process struct {
	Bin    string   // the program to run
	Args   []string // its arguments
	Dir    string   // child working directory; the process's own when empty
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer
}

Process is a child run with the caller's own streams, as exec runs a tool.

type ProcessRunner

type ProcessRunner interface {
	Run(ctx context.Context, p Process) (code int, err error)
}

ProcessRunner runs a Process. The code is the child's exit status, 128+n when signal n killed it. The error is non-nil only when the child could not be run at all: a child stopped by the context reports its signal as the code.

type Result

type Result struct {
	Stdout []byte
	Stderr []byte
	Code   int
}

Result is a finished go invocation.

type Runner

type Runner interface {
	Run(ctx context.Context, c Call) (Result, error)
}

Runner runs the go command. The error is non-nil only when go could not be run (ErrNotFound, a cancelled context, a *TimeoutError).

func WithTimeout

func WithTimeout(r Runner, d time.Duration) Runner

WithTimeout returns a Runner whose calls are bounded by d. A d of 0 or less disables the bound. A context cancelled by the caller is reported as itself, not as a timeout.

Example

A timeout bounds any runner, so the same code runs with the real go or a fake.

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/piusalfred/gotools/internal/gocmd"
)

type slow struct{ d time.Duration }

func (s slow) Run(ctx context.Context, _ gocmd.Call) (gocmd.Result, error) {
	select {
	case <-time.After(s.d):
		return gocmd.Result{}, nil
	case <-ctx.Done():
		return gocmd.Result{}, ctx.Err()
	}
}

func main() {
	var r gocmd.Runner = slow{time.Minute}

	_, err := gocmd.WithTimeout(r, 10*time.Millisecond).Run(context.Background(), gocmd.Call{Args: []string{"get", "-tool", "example.com/x"}})

	fmt.Println(err)

}
Output:
timed out after 10ms

type TimeoutError

type TimeoutError struct {
	After time.Duration
}

TimeoutError reports that a bounded run exceeded its limit.

func (*TimeoutError) Error

func (e *TimeoutError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL