---
title: Go Package
description: Provision an official Go SDK, run or install Go tools, and build Go binaries.
---

# Go Package

The Go package provisions a specific official Go SDK and exposes it as a dependency. A global Go installation is not needed when xx runs the build.

Load it with an exact Go release version, without the `go` prefix:

```python
load("@go@1.26.5", "go", "go_binary", "go_install", "go_run")
```

Stable versions such as `1.26.0` and `1.26.5`, plus official `beta` and `rc` versions, use the corresponding release from [go.dev](https://go.dev/dl/). A version absent from official Go metadata fails instead of silently selecting another version.

## `go`

`go` is a dependency that provisions and activates the selected SDK. Use it with [`run`](os.md#run) when calling Go commands directly:

```python
load("@go@1.26.5", "go")
load("@os@1", "run")

run(("go", "test", "./..."), deps=[go])
```

Activation puts the managed SDK's binary directory and a command-scoped temporary `GOBIN` first in `PATH`, then configures isolated Go storage below xx's Go cache. The temporary directory is shared by entrypoints in one `xx run` command and removed after every task finishes. This prevents tools from remaining available after their install declaration is removed.

| Variable | Behavior |
| --- | --- |
| `PATH` | Managed SDK `bin`, then temporary `GOBIN`, then existing entries |
| `GOBIN` | Command-scoped temporary application directory |
| `GOROOT` | Managed SDK directory |
| `GOCACHE` | Shared managed build cache |
| `GOMODCACHE` | Shared managed module cache |
| `GOPATH` | Shared managed workspace |
| `GOTOOLCHAIN` | `local`, preventing Go from switching toolchains |
| `GOENV` | `off`, preventing a user Go environment file from changing the build |

Other task dependencies can add or override environment values in their declared order. `go_binary`, `go_install`, and `go_run` always restore their managed `GOROOT`, `GOTOOLCHAIN`, and `GOENV` immediately before invoking Go. `go_install` also restores its isolated `GOBIN`.

## `go_run`

Run a Go command at a required version without installing it first:

```python
load("@go@1.26.5", "go_run")

go_run(
    package="codeberg.org/tsukinoko-kun/doctopus",
    version="latest",
    args=["build"],
)
```

`go_run` invokes `go run <package>@<version> <args...>` with the selected managed SDK. Package and version follow the same rules as `go_install` and must be non-empty strings.

| Argument | Required | Description |
| --- | --- | --- |
| `package` | Yes | Go package path without an `@version` suffix |
| `version` | Yes | Version query appended to the package path |
| `args` | No | String arguments passed to the Go command |
| `deps` | No | Dependencies activated before running the command, in list order |

The selected Go SDK is an implicit dependency. `go_run` returns a dependency and also registers the command as a root task, matching `go_install` and `go_binary` behavior.

## `go_install`

Install a Go command at a required version:

```python
load("@go@1.26.5", "go_install")
load("@os@1", "run")

doctopus = go_install(
    package="codeberg.org/tsukinoko-kun/doctopus",
    version="latest",
)
run(("doctopus", "build"), deps=[doctopus])
```

`go_install` invokes `go install <package>@<version>` with the selected managed SDK. It accepts Go version queries such as `latest`, branch names such as `main`, semantic versions, and revisions without restricting their format. Both `package` and `version` must be non-empty strings.

| Argument | Required | Description |
| --- | --- | --- |
| `package` | Yes | Go package path without an `@version` suffix |
| `version` | Yes | Version query appended to the package path |
| `deps` | No | Dependencies activated before installation, in list order |

The selected Go SDK is an implicit installation dependency. Each SDK and package version uses a dedicated directory below the temporary `GOBIN`, preventing concurrent installs from replacing each other's commands. The returned dependency adds that directory to `PATH` after the managed SDK, so installed commands are available to tasks that depend on it without shadowing `go`. All installed commands are deleted when the `xx run` command finishes and must be declared again in later runs. Declaring the same SDK, package, and version more than once in one run is rejected as an output conflict.

## `go_binary`

Build a Go command from one source file or one package directory:

```python
go_binary(
    entry_point="cmd/server",
    deps=[],
    output="bin/server",
    flags=["-trimpath"],
)
```

### Arguments

| Argument | Required | Description |
| --- | --- | --- |
| `entry_point` | Yes | Project-relative Go source file or package directory passed to `go build` |
| `deps` | No | Dependencies activated before the build, in list order |
| `output` | No | Project-relative output file |
| `flags` | No | String arguments inserted after `go build` and before xx's output and entrypoint arguments |

The selected Go SDK is always an implicit dependency. Do not add `go` to `deps` for `go_binary`.

### Default Output

When `output` is omitted, xx writes to `.xx/out/<name>`:

- `entry_point="main.go"` becomes `.xx/out/main`.
- `entry_point="cmd/server"` becomes `.xx/out/server`.
- `entry_point="."` uses the project directory name.
- Windows adds `.exe` to a default output name.

A custom output is used exactly as written, including its extension. xx creates missing parent directories.

Use the `output` argument instead of passing `-o`, `--o`, `-o=...`, or `--o=...` in `flags`. Those forms are rejected so xx can validate and reserve the output safely.

### Paths and Conflicts

Entrypoints and outputs must stay inside the project, including after symlinks are resolved. An output cannot replace its entrypoint, point to an existing directory, or overlap another active build output. These checks prevent concurrently running tasks from writing the same path.

## SDK Download and Cache

On first use, xx reads official Go release metadata, downloads the portable archive for the host, verifies its exact size and SHA-256 checksum, validates the extracted SDK, and publishes it into the operating-system user cache under `xx/go/<version>`.

Later builds reuse a valid cached SDK. Concurrent tasks requesting the same version share setup work. An invalid cached SDK is removed and provisioned again.

Supported SDK hosts:

- Windows x86-64 (`windows/amd64`)
- Windows ARM64 (`windows/arm64`)
- Linux x86-64 (`linux/amd64`)
- Linux ARM64 (`linux/arm64`)
- macOS ARM64 (`darwin/arm64`)

Unsupported hosts, missing official archives, and checksum mismatches fail with an error.

## Examples

See [Go examples](../examples/go.md) for complete build files covering binaries, package directories, flags, environment dependencies, and direct Go commands.

<!--
Sitemap

URL: https://withxx.dev/index.md
Title: xx
Description: Practical, reproducible builds without build-system ceremony

URL: https://withxx.dev/examples/commands.md
Title: Command Examples
Description: General command, environment, and entrypoint patterns.

URL: https://withxx.dev/examples/go.md
Title: Go Examples
Description: Common Go build patterns with managed SDKs.

URL: https://withxx.dev/examples/index.md
Title: Examples
Description: Common xx build and task patterns.

URL: https://withxx.dev/examples/nodejs.md
Title: Node.js Examples
Description: Common Node.js task patterns with a managed distribution.

URL: https://withxx.dev/load.md
Title: Loading Files
Description: Split xx configuration into local Starlark modules.

URL: https://withxx.dev/packages/go.md
Title: Go Package
Description: Provision an official Go SDK, run or install Go tools, and build Go binaries.

URL: https://withxx.dev/packages/nodejs.md
Title: Node.js Package
Description: Provision official Node.js distributions and run npm and npx tasks.

URL: https://withxx.dev/packages/os.md
Title: OS Package
Description: Run commands and construct isolated task environments.
-->
