Go idioms, style guide, and best practices with YAGNI/KISS principles. Use when writing or reviewing Go code.
This skill inherits all available tools. When active, it can use any tool Claude has access to.
This skill provides Go code quality standards with YAGNI/KISS development philosophy.
Use this skill when:
Example:
// Good - Simple, addresses current need
func GetUser(id int) (*User, error) {
return db.Query("SELECT * FROM users WHERE id = ?", id)
}
// Bad - YAGNI violation, adding unused caching
func GetUser(id int) (*User, error) {
if cached, ok := cache.Get(id); ok {
return cached, nil
}
user, err := db.Query("SELECT * FROM users WHERE id = ?", id)
if err == nil {
cache.Set(id, user)
}
return user, err
}
Example:
// Good - Simple and clear
func Sum(numbers []int) int {
sum := 0
for _, n := range numbers {
sum += n
}
return sum
}
// Bad - Unnecessary complexity
func Sum(numbers []int) int {
ch := make(chan int)
go func() {
sum := 0
for _, n := range numbers {
sum += n
}
ch <- sum
}()
return <-ch
}
go fmt after changesgoimports for import management./bin/ directorymake build, never go build directlyfmt, test, lint, clean targets// Good naming
type UserService struct {}
func (s *UserService) GetUser(ctx context.Context, id int) (*User, error)
var ErrNotFound = errors.New("not found")
const MaxRetries = 3
// Bad naming
type Userservice struct {}
func (s *Userservice) get_user(ID int) (*User, error)
var errnotfound = errors.New("not found")
const max_retries = 3
Rules:
HTTP, ID, URL// Good - grouped by functionality
package user
type Service struct {}
type Repository struct {}
type Handler struct {}
// Bad - grouped by type
package services
type UserService struct {}
type OrderService struct {}
// Good - small, focused interfaces
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// Bad - large interface
type FileManager interface {
Read(p []byte) (n int, err error)
Write(p []byte) (n int, err error)
Close() error
Seek(offset int64, whence int) (int64, error)
Stat() (FileInfo, error)
}
Rules:
// Good - context, clear naming, simple logic
func (s *Service) GetUser(ctx context.Context, id int) (*User, error) {
user, err := s.repo.FindByID(ctx, id)
if err != nil {
return nil, fmt.Errorf("failed to get user: %w", err)
}
return user, nil
}
// Bad - missing context, unclear error
func (s *Service) GetUser(id int) (*User, error) {
user, err := s.repo.FindByID(id)
if err != nil {
return nil, err
}
return user, nil
}
// Good - context first parameter
func ProcessRequest(ctx context.Context, req Request) error {
// Check cancellation
select {
case <-ctx.Done():
return ctx.Err()
default:
}
return doWork(ctx, req)
}
// Bad - missing context
func ProcessRequest(req Request) error {
return doWork(req)
}
// Good structure
type Server struct {
host string
port int
}
func NewServer(host string, port int) *Server {
return &Server{host: host, port: int}
}
func (s *Server) Start() error {
// implementation
}
// Bad - scattered functions
func StartServer(host string, port int) error {}
func StopServer(s *Server) error {}
type Server struct {
host string
port int
timeout time.Duration
}
type Option func(*Server)
func WithHost(host string) Option {
return func(s *Server) { s.host = host }
}
func WithPort(port int) Option {
return func(s *Server) { s.port = port }
}
func NewServer(opts ...Option) *Server {
s := &Server{
host: "localhost",
port: 8080,
timeout: 30 * time.Second,
}
for _, opt := range opts {
opt(s)
}
return s
}
// Usage
srv := NewServer(WithHost("0.0.0.0"), WithPort(3000))
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
want int
}{
{"positive", 1, 2, 3},
{"negative", -1, -2, -3},
{"mixed", 1, -1, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Add(tt.a, tt.b)
if got != tt.want {
t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, got, tt.want)
}
})
}
}
.PHONY: build test clean fmt lint
build:
\t@mkdir -p bin
\tgo build -o bin/myapp cmd/myapp/main.go
fmt:
\tgo fmt ./...
test:
\tgo test -v ./...
lint:
\tgolangci-lint run
clean:
\trm -rf bin/
Create .golangci.yml:
linters:
enable:
- gofmt
- goimports
- govet
- errcheck
- staticcheck
- gosec
- gosimple
- ineffassign
- unused
linters-settings:
gofmt:
simplify: true
goimports:
local-prefixes: github.com/yourorg/
// Bad - optimizing without profiling
type Cache struct {
mu sync.RWMutex
items map[string]*Item
}
// Good - start simple (KISS)
type Cache struct {
items map[string]*Item
}
// Bad - YAGNI violation
type UserFactory interface {
CreateUser() User
}
type StandardUserFactory struct {}
func (f *StandardUserFactory) CreateUser() User {
return User{}
}
// Good - simple and direct
func NewUser() User {
return User{}
}
// Bad
data, _ := ioutil.ReadFile("file.txt")
// Good
data, err := ioutil.ReadFile("file.txt")
if err != nil {
return fmt.Errorf("failed to read file: %w", err)
}