en un clic
xe-go-style
// Write Go code following the conventions and patterns used in the within.website/x repository, including CLI patterns, error handling, logging with slog, HTTP handlers, and testing.
// Write Go code following the conventions and patterns used in the within.website/x repository, including CLI patterns, error handling, logging with slog, HTTP handlers, and testing.
| name | xe-go-style |
| description | Write Go code following the conventions and patterns used in the within.website/x repository, including CLI patterns, error handling, logging with slog, HTTP handlers, and testing. |
Write Go code following the conventions and patterns used by Xe Iaso.
├── cmd/ # Main applications (each subdirectory is a binary)
│ ├── x/ # 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
└── gen/ # Generated code (protobuf)
Package naming: lowercase, single words preferred (slog, flagenv, kahless).
All command-line tools MUST call flagenv.Parse() and then flag.Parse().
package main
import (
"flag"
"github.com/facebookgo/flagenv"
)
var (
bind = flag.String("bind", ":8080", "HTTP bind address")
dbLoc = flag.String("db-loc", "", "Database location")
)
func main() {
flagenv.Parse()
flag.Parse()
}
Configuration loading order: flags → env vars (flagenv) → flags (final override).
Use github.com/google/subcommands for subcommand-based CLIs:
package main
import (
"context"
"flag"
"os"
"github.com/facebookgo/flagenv"
"github.com/google/subcommands"
)
func main() {
flagenv.Parse()
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.
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 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),
)
}
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()),
)
}
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()
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:
tt as the loop variable in table-driven testsname field for subtestst.Helper() for helper functionst.Parallel() for independent testst.TempDir() for temporary directorieshttptest.NewServer() for HTTP mockingerrors.Is() for error comparisont.Logf("want: %v", x) and t.Logf("got: %v", y) for debuggingfunc loadConfig(t *testing.T, fname string) config.Toplevel {
t.Helper()
// ...
}
go fmt/goimports for formattingcamelCase for variablesPascalCase for exported identifiersA warm, Gruvbox-rooted design system derived from xeiaso.net. Use for personal-blog, technical-educator, or character-driven content that wants serif headlines, parchment surfaces, and chat-bubble layouts. Distinctive: magenta inverted link hovers, boxy 2px-radius sticker avatars, no gradients except the SponsorCard top rule.
Write GORM data access code using the DAO (Data Access Object) pattern. Use when creating database models, writing queries, setting up GORM, adding CRUD methods, or working with gorm.io in Go services. Also use when the user mentions "DAO", "data access", "ORM", "database models", "GORM", or is building a Go service that talks to a relational database.
Create reusable templ UI components with props, children, and composition patterns. Use when building UI components, creating component libraries, mentions 'button component', 'card component', or 'reusable templ components'.
Build interactive hypermedia-driven applications with templ and HTMX. Use when creating dynamic UIs, real-time updates, AJAX interactions, mentions 'HTMX', 'dynamic content', or 'interactive templ app'.
Integrate templ components with Go HTTP server using net/http. Use when connecting templ to web server, creating HTTP handlers, mentions 'templ server', 'HTTP routes', or 'serve templ components'.
Learn and write templ component syntax including expressions, conditionals, loops, and Go integration. Use when writing .templ files, learning templ syntax, or mentions 'templ component', 'templ expressions', or '.templ file syntax'.