= 1: Go
:page-pagination: next

This is a minimal sample for Zilch's Go support, intended to show off the
ability to edit dependencies with ease, without losing the reproducibility that
Zilch provides.

To start, run `zilch-cli-go -m examples/go` and see the resulting binary
operate:

[,console]
----
$ zilch-cli-go -m examples/go
example.com/go	/nix/store/wh1iaiplnkznh8x4rgqxs89qn90xaf3v-example.com_go

$ /nix/store/wh1iaiplnkznh8x4rgqxs89qn90xaf3v-example.com_go
1980-01-01T13:37:00.000Z	INFO	main/main.go:9	This is an example Go program.	{"exampleString": "yes", "example": true}
----

---

If, say, you find a bug (e.g. you are of the opinion the line number should come
before the file name), this has to be patched in the logging module, which is
provided by zap. Clone the repo (`https://github.com/uber-go/zap`). In our case
we have it at `./zap`. To make sure the bug isn't patched in this current
version, let's first try building the example program again with it. This can be
done with the `--replace` command, or `-r` for short. This takes a directory
with a `go.mod`, and prioritizes it over the version of the Go module used in
the `go.mod` of the main module.

[,console]
----
$ zilch-cli-go -m examples/go -r zap
example.com/go	/nix/store/75r8574ccq8vhsjyrr8jm9icdy5f19c1-example.com_go

$ /nix/store/75r8574ccq8vhsjyrr8jm9icdy5f19c1-example.com_go
1980-01-01T13:37:00.000Z	INFO	main/main.go:9	This is an example Go program.	{"exampleString": "yes", "example": true}
----

Sadly, after updating, nothing changed. So we'll have to make changes. The
filename and line number are written in `zap/zapcore/entry.go`, around line 91;
inside `FullPath()`. After patching the function to swap them around, rerunning
the `zilch-cli-go` command shown previously will go through and recompile only
the changed files. So:

[,console]
----
$ zilch-cli-go -m examples/go -r zap
example.com/go	/nix/store/vl6dd9d4ry7xhh31vpimjsn9khpqmxgb-example.com_go

$ /nix/store/vl6dd9d4ry7xhh31vpimjsn9khpqmxgb-example.com_go
1980-01-01T13:37:00.000Z	INFO	9:main/main.go	This is an example Go program.	{"exampleString": "yes", "example": true}
----

As you can see, the bug is fixed, by testing with a project in a different repo!

---

Whenever you run `zilch-cli-go`, the script runs from scratch, not using any
previous information. It performs a series of steps to build a build graph:

First, it walks the `go.mod` of the main module, as well as all its
dependencies, using the `go.sum` as a guide to ensure this all stays content-
addressed, similar to the `go` tool. Once it has all the modules that are used
in the program, it looks for all packages inside each of the modules. Each
package is then analyzed for which other packages it imports, which is used to
build Zilch-native build information.

At this point, enough information has been gathered to build the resulting
build graph. The main package's derivation is materialized into the Nix store,
and with it, all its dependencies are pulled in. All its dependencies are built
with two outputs; both the native code and the API are separately stored. This
ensures that any changes that don't affect the interface that other packages
depend on do not cause a butterfly effect, and stay localized to the native
code.

At no point does Zilch run any of this code on the local system, either. All
builds and information gathering are done entirely inside the Nix daemon, which
provides for a stable and sandboxed environment.
