skills/go-bootstrap/SKILL.md
Guidelines and conventions for bootstrapping Go modules, project structures, and reliable production patterns (HTTP servers, database connections). Activate on module initialization, new service creation, layout scoping, or setup requests.
npx skillsauth add danicat/godoctor go-bootstrapInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill provides step-by-step instructions for establishing a modern, robust, and idiomatic Go module layout. It strictly follows official Go guidelines and emphasizes simplicity, compiler-safety, and production-ready architectures.
We adhere strictly to the official go.dev/doc/modules/layout conventions.
Keep all Go files in the root directory. It is simpler, avoids redundant packaging, and prevents import cycles.
my-service/
├── go.mod
├── go.sum
├── main.go
├── server.go
├── database.go
└── server_test.go
Rule of thumb: Start flat. Do not over-engineer with nested folders like pkg/ or internal/ until scale or the need for multiple binaries warrants it.
Use a nested structure only when creating multiple executable binaries or protecting private package APIs from external imports.
my-app/
├── go.mod
├── go.sum
├── cmd/
│ ├── api-server/
│ │ └── main.go
│ └── cli-tool/
│ └── main.go
└── internal/
├── auth/
│ └── auth.go
└── db/
└── db.go
cmd/: Contains subdirectories for each executable binary. Keep code in cmd/ minimal (only main.go and flag parsing/initialization).internal/: Contains private application packages. Go compiler strictly blocks other modules from importing anything under internal/.pkg/: NEVER use pkg/ in modern idiomatic Go. It is a legacy/non-standard convention that adds redundant path depth.Always implement graceful shutdown on HTTP servers to prevent dropped requests during deployments.
package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func run(ctx context.Context) error {
// Setup termination signal catching
ctx, stop := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
defer stop()
mux := http.NewServeMux()
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
srv := &http.Server{
Addr: ":8080",
Handler: mux,
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
}
// Start server in background
serverErr := make(chan error, 1)
go func() {
log.Printf("Listening on %s", srv.Addr)
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
serverErr <- err
}
}()
// Wait for shutdown or error
select {
case err := <-serverErr:
return err
case <-ctx.Done():
log.Println("Shutting down server gracefully...")
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10 * time.Second)
defer cancel()
return srv.Shutdown(shutdownCtx)
}
}
func main() {
if err := run(context.Background()); err != nil {
log.Fatalf("Application error: %v", err)
}
}
database/sql)Ensure connection limits and idle timeouts are configured on your *sql.DB instance to prevent leaks and handle transient failures.
package main
import (
"context"
"database/sql"
"time"
)
func initDB(ctx context.Context, dsn string) (*sql.DB, error) {
db, err := sql.Open("pgx", dsn) // or other driver
if err != nil {
return nil, err
}
// Establish connection pool limits
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(25)
db.SetConnMaxLifetime(5 * time.Minute)
db.SetConnMaxIdleTime(3 * time.Minute)
// Verify database is reachable with a timeout
pingCtx, cancel := context.WithTimeout(ctx, 3 * time.Second)
defer cancel()
if err := db.PingContext(pingCtx); err != nil {
db.Close()
return nil, err
}
return db, nil
}
project_init to create the target directory and run go mod init <module_path>.main.go, server.go, etc.) using smart_edit.add_dependency.smart_build to verify the entire module compiles and tests successfully.development
Guidelines and templates for structuring software development goals and ideas into actionable, bounded tasks using Context/Todo/AC, enforced by the DoR gate. Activate when scoping user requests, decomposing RFCs into tasks, or creating a new task file.
development
Guidelines and templates for authoring Request for Comments (RFCs). Activate when proposing significant features/refactorings, exploring design alternatives under high ambiguity, or gathering technical consensus.
development
Pre-release checklist and quality gate to verify codebase health, docs, and security before interacting with Git. Activate when preparing to tag/publish a release, concluding milestones, or running final verification on a pull request.
development
Highly actionable step-by-step checklist for diagnosing and resolving Go compilation errors, type errors, build/test failures, and runtime issues. Activate on any build or execution failure.