func initGoEnv() error {
	var err error
	run := func(args ...string) (*bytes.Buffer, *bytes.Buffer, error) {
		var stdout, stderr bytes.Buffer
		cmd := exec.Command(args[0], args[1:]...)
		cmd.Stdout = &stdout
		cmd.Stderr = &stderr
		return &stdout, &stderr, cmd.Run()
	}
	lout, stderr, err := run("go", "list", "-f={{context.ReleaseTags}}", "runtime")
	if err != nil {
		return fmt.Errorf("failed to determine release tags from go command: %v\n%v", err, stderr.String())
	}
	tagStr := strings.TrimSpace(lout.String())
	tagStr = strings.Trim(tagStr, "[]")
	goEnv.releaseTags = strings.Split(tagStr, " ")
	eout, stderr, err := run("go", "env", "-json",
		"GOROOT",
		"GOCACHE",
		"GOPROXY",
	)
	if err != nil {
		return fmt.Errorf("failed to determine environment from go command: %v\n%v", err, stderr)
	}
	if err := json.Unmarshal(eout.Bytes(), &goEnv); err != nil {
		return fmt.Errorf("failed to unmarshal GOROOT and GOCACHE tags from go command out: %v\n%v", err, eout)
	}
	version := goEnv.releaseTags[len(goEnv.releaseTags)-1]
	if !goVersionRegex.MatchString(version) {
		return fmt.Errorf("invalid go version %q", version)
	}
	goEnv.goversion = version[2:]
	return nil
}
initGoEnv initialises goEnv. It should only be called using goEnv.once.Do,
as in Setup.
package gotooltest
import (
	"bytes"
	"encoding/json"
	"fmt"
	"go/build"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
	"sync"
	"github.com/rogpeppe/go-internal/testscript"
)
var (
	goVersionRegex = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
	goEnv struct {
		GOROOT      string
		GOCACHE     string
		GOPROXY     string
		goversion   string
		releaseTags []string
		once        sync.Once
		err         error
	}
)