Xe/x Go Style Guide
Write Go code following the conventions and patterns used in the within.website/x repository (Go 1.25.4).
Project Structure
├── cmd/ # Main applications (each subdirectory is a binary)
│ ├── x/ # Main CLI with subcommands
│ │ ├── main.go
│ │ └── cmd/ # Subcommand packages
│ └── sakurajima/ # Service binaries
│ ├── main.go
│ └── internal/ # Command-specific internal packages
├── internal/ # Private packages shared across commands
├── web/ # Web-related services and API clients
├── writer/ # Utility libraries for io.Writer middleware
└── gen/ # Generated code (protobuf)
Package naming: lowercase, single words preferred (slog, flagenv, kahless).
CLI Pattern (CRITICAL)
All command-line tools MUST call internal.HandleStartup() at the start of main(). This function handles configuration loading and calls flag.Parse(). Individual binaries MUST NOT call flag.Parse() themselves.
package main
import (
"flag"
"within.website/x/internal"
)
var (
bind = flag.String("bind", ":8080", "HTTP bind address")
dbLoc = flag.String("db-loc", "", "Database location")
)
func main() {
internal.HandleStartup() // NO flag.Parse() call!
// flags are now parsed, use *bind and *dbLoc here
}
Configuration loading order: flags → env vars (flagenv) → /run/secrets (flagfolder) → config file (flagconfyg) → flags (final override).
Subcommands
Use github.com/google/subcommands for subcommand-based CLIs:
package main
import (
"context"
"flag"
"os"
"github.com/google/subcommands"
"within.website/x/internal"
)
func main() {
internal.HandleStartup()
subcommands.Register(subcommands.HelpCommand(), "")
subcommands.Register(subcommands.FlagsCommand(), "")
subcommands.Register(subcommands.CommandsCommand(), "")
subcommands.Register(&serveCmd{}, "")
subcommands.Register(&versionCmd{}, "")
os.Exit(int(subcommands.Execute(context.Background())))
}
type serveCmd struct {
dbLoc string
}
func (c *serveCmd) Name() string { return "serve" }
func (c *serveCmd) Synopsis() string { return "Start the server" }
func (c *serveCmd) Usage() string {
return "serve [flags]\nStart the HTTP server.\n"
}
func (c *serveCmd) SetFlags(f *flag.FlagSet) {
f.StringVar(&c.dbLoc, "db-loc", "", "Database location")
}
func (c *serveCmd) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
// Implementation
return subcommands.ExitSuccess
}
Flag names use kebab-case: --db-loc, --grpc-bind, --slog-level.
Error Handling
Define package-level sentinel errors:
var ErrNotFound = errors.New("store: key not found")
var ErrCantDecode = errors.New("store: can't decode value")
Wrap errors with context using %w:
if err != nil {
return nil, fmt.Errorf("failed to connect to database: %w", err)
}
return nil, fmt.Errorf("ollama: error encoding request: %w", err)
Combine multiple validation errors with errors.Join:
func (t *Toplevel) Valid() error {
var errs []error
if err := t.Bind.Valid(); err != nil {
errs = append(errs, fmt.Errorf("invalid bind block:\n%w", err))
}
if len(errs) != 0 {
return fmt.Errorf("invalid configuration file:\n%w", errors.Join(errs...))
}
return nil
}
Check errors with errors.Is() and errors.As():
if errors.Is(err, ErrNotFound) {
// handle not found
}
Custom error types implement Error() and optionally slog.LogValue():
type Error struct {
WantStatus, GotStatus int
URL *url.URL
Method string
ResponseBody string
}
func (e Error) Error() string {
return fmt.Sprintf("%s %s: wanted status code %d, got: %d: %v",
e.Method, e.URL, e.WantStatus, e.GotStatus, e.ResponseBody)
}
func (e Error) LogValue() slog.Value {
return slog.GroupValue(
slog.Int("want_status", e.WantStatus),
slog.Int("got_status", e.GotStatus),
slog.String("url", e.URL.String()),
slog.String("method", e.Method),
slog.String("body", e.ResponseBody),
)
}
Logging
Use log/slog (never the plain log package). Output JSON to stderr. Use -slog-level flag for runtime control.
slog.Info("starting up",
"bind", *bind,
"db-loc", *dbLoc,
)
slog.Error("failed to create dao", "err", err)
slog.Debug("processing", "count", len(items))
Always use "err" as the key for errors. Implement LogValue() for complex types:
func (s *Show) LogValue() slog.Value {
return slog.GroupValue(
slog.String("title", s.GetTitle()),
slog.String("disk_path", s.GetDiskPath()),
)
}
HTTP Patterns
Middleware pattern:
func PasswordMiddleware(username, password string, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, pass, ok := r.BasicAuth()
if !ok || user != username || pass != password {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
Chaining middleware:
var h http.Handler = topLevel
h = xffMW.Handler(h)
h = cors.Default().Handler(h)
h = FlyRegionAnnotation(h)
HTTP client with context and error handling:
func (c *Client) doRequest(ctx context.Context, method, path string, wantCode int, body io.Reader) (*http.Response, error) {
req, err := http.NewRequestWithContext(ctx, method, u.String(), body)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
resp, err := c.http.Do(req)
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
}
if resp.StatusCode != wantCode {
return nil, web.NewError(wantCode, resp)
}
return resp, nil
}
Server lifecycle with errgroup:
g, gCtx := errgroup.WithContext(ctx)
g.Go(func() error {
ln, err := net.Listen("tcp", cfg.Bind.HTTP)
if err != nil {
return fmt.Errorf("failed to listen: %w", err)
}
return rtr.HandleHTTP(gCtx, ln)
})
return g.Wait()
Testing
Tests co-located with source (*_test.go). Use table-driven tests:
func TestDomainValid(t *testing.T) {
t.Parallel()
for _, tt := range []struct {
name string
input Domain
err error
errContains string
}{
{name: "simple happy path", input: Domain{Name: "example.com"}},
{name: "invalid domain", input: Domain{Name: "\uFFFD.com"}, err: ErrInvalidDomainName},
} {
t.Run(tt.name, func(t *testing.T) {
err := tt.input.Valid()
if tt.err != nil {
if !errors.Is(err, tt.err) {
t.Logf("want: %v", tt.err)
t.Logf("got: %v", err)
t.Error("got wrong error")
}
}
})
}
}
Testing best practices:
- Use
ttas the loop variable in table-driven tests - Always include
namefield for subtests - Use
t.Helper()for helper functions - Use
t.Parallel()for independent tests - Use
t.TempDir()for temporary directories - Use
httptest.NewServer()for HTTP mocking - Use
errors.Is()for error comparison - Include
t.Logf("want: %v", x)andt.Logf("got: %v", y)for debugging
func loadConfig(t *testing.T, fname string) config.Toplevel {
t.Helper()
// ...
}
Code Style
- Use
go fmt/goimportsfor formatting - Tabs for indentation
camelCasefor variablesPascalCasefor exported identifiers- Files use snake_case
- Packages use lower-case module names
- Run
npm run formatbefore committing