go
What I do
I help you write Go code that follows professional style guide conventions based on Google's Go Style Guide. This includes:
- Enforcing naming conventions (MixedCaps, mixedCaps)
- Applying proper documentation and commentary
- Managing imports correctly (grouping, ordering, renaming)
- Following formatting rules (gofmt compliant)
- Implementing error handling patterns
- Writing clear, simple, and maintainable code
- Applying concurrency best practices
- Structuring packages effectively
When to use me
Use this skill when:
- Writing new Go code that should follow style guide conventions
- Refactoring existing Go code to match best practices
- Reviewing Go code for style compliance
- Adding documentation to Go packages, functions, or types
- Organizing imports in Go files
- Designing APIs and interfaces
- Handling errors appropriately
Style Principles
Go style follows these core principles in order of importance:
- Clarity - The code's purpose and rationale is clear to the reader
- Simplicity - The code accomplishes its goal in the simplest way possible
- Concision - The code has a high signal-to-noise ratio
- Maintainability - The code can be easily maintained
- Consistency - The code is consistent with the broader codebase
Key style rules I enforce
Formatting
All Go source files must conform to gofmt output:
gofmt -w .
- No fixed line length (prefer refactoring over splitting)
- Use
MixedCapsormixedCaps(never snake_case) - Let the code speak for itself when possible
Naming Conventions
Packages:
// Good
package creditcard
package tabwriter
package oauth2
// Bad
package credit_card
package tabWriter
package oAuth2
Functions and Methods:
// Good - avoid repetition with package name
package yamlconfig
func Parse(input string) (*Config, error)
// Bad - repetitive
func ParseYAMLConfig(input string) (*Config, error)
Variables:
- Short names in small scopes:
i,c,db - Longer names in larger scopes:
userCount,databaseConnection - Avoid type in name:
usersnotuserSlice
Constants:
// Good
const MaxPacketSize = 512
const ExecuteBit = 1 << iota
// Bad
const MAX_PACKET_SIZE = 512
const kMaxBufferSize = 1024
Initialisms: Keep same case throughout:
// Good
func ServeHTTP(w http.ResponseWriter, r *http.Request)
func ProcessXMLAPI() error
var userID string
// Bad
func ServeHttp()
func ProcessXmlApi()
var userId string
Receiver Names:
- Short (1-2 letters)
- Abbreviation of type
- Consistent across methods
// Good
func (c *Client) Get(url string) (*Response, error)
func (c *Client) Post(url string, body io.Reader) (*Response, error)
// Bad
func (client *Client) Get(url string) (*Response, error)
func (this *Client) Post(url string, body io.Reader) (*Response, error)
Documentation
Package Comments:
// Package math provides basic constants and mathematical functions.
//
// This package does not guarantee bit-identical results across architectures.
package math
Function Comments:
// Good - complete sentence starting with function name
// Join concatenates the elements of its first argument to create a single string.
// The separator string sep is placed between elements in the resulting string.
func Join(elems []string, sep string) string
// Bad
// This function joins strings
func Join(elems []string, sep string) string
Comment Sentences:
- Complete sentences for doc comments
- Capitalize and punctuate properly
- Start with the name being described
Imports
Import Grouping (separated by blank lines):
- Standard library packages
- Other (project and vendored) packages
- Protocol Buffer imports
- Side-effect imports
// Good
package main
import (
"fmt"
"hash/adler32"
"os"
"github.com/dsnet/compress/flate"
"golang.org/x/text/encoding"
foopb "myproj/foo/proto/proto"
_ "myproj/rpc/protocols/dial"
)
Import Renaming:
// Good - clear and descriptive
import (
foogrpc "path/to/package/foo_service_go_grpc"
foopb "path/to/package/foo_service_go_proto"
)
// Avoid - unless necessary
import (
foo "some/really/long/package/path"
)
Never use import dot (except in tests):
// Bad
import . "foo"
// Good
import "foo"
Error Handling
Return errors, don't panic:
// Good
func Open(path string) (*File, error) {
f, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("open %s: %w", path, err)
}
return f, nil
}
// Bad - don't panic on errors
func Open(path string) *File {
f, err := os.Open(path)
if err != nil {
panic(err)
}
return f
}
Error strings:
// Good - lowercase, no punctuation
err := fmt.Errorf("something bad happened")
// Bad
err := fmt.Errorf("Something bad happened.")
Handle errors:
// Good
if err := doSomething(); err != nil {
return fmt.Errorf("failed to do something: %w", err)
}
// Bad - ignoring errors
_ = doSomething()
Indent error flow:
// Good
if err != nil {
// error handling
return err
}
// normal code
// Bad - avoid else after error
if err != nil {
// error handling
} else {
// normal code
}
Error wrapping:
// Good - use %w to wrap errors for errors.Is/As
return fmt.Errorf("process failed: %w", err)
// Good - use %v when you don't want wrapping
return fmt.Errorf("process failed: %v", err)
Function Design
Keep signatures simple:
// Good - signature on one line
func (r *Reader) Read(p []byte) (n int, err error)
// Good - named results when helpful
func WithTimeout(parent Context, d time.Duration) (ctx Context, cancel func())
// Bad - naked returns in long functions
func Process() (result int, err error) {
// ... many lines ...
result = 42
return // unclear what's being returned
}
Avoid repetition:
// Good
func (c *Config) WriteTo(w io.Writer) (int64, error)
// Bad - repetitive
func (c *Config) WriteConfigTo(w io.Writer) (int64, error)
Nil Slices
Prefer nil slices over empty slices:
// Good
var s []int // nil slice, len=0, cap=0
// Acceptable in most cases
s := []int{} // non-nil empty slice
// Don't force distinction between nil and empty
if len(s) == 0 { // works for both nil and empty
// ...
}
// Bad
if s == nil { // usually not what you want
// ...
}
Interfaces
Small interfaces:
// Good - single method interface
type Reader interface {
Read(p []byte) (n int, err error)
}
// Good - composed interfaces
type ReadWriter interface {
Reader
Writer
}
Accept interfaces, return structs:
// Good
func Process(r io.Reader) (*Result, error)
// Avoid unless necessary
func Process(r *os.File) (*Result, error)
Concurrency
Document concurrency:
// Good - document when NOT safe
// Cache stores expensive computation results.
//
// Methods are not safe for concurrent use.
type Cache struct { ... }
// Good - document when safe
// Client is safe for concurrent use by multiple goroutines.
type Client struct { ... }
Context usage:
// Good - context as first parameter
func Process(ctx context.Context, data []byte) error
// Document if context behavior is special
// Run executes the worker's run loop.
//
// If the context is cancelled, Run returns a nil error.
func (w *Worker) Run(ctx context.Context) error
Testing
Table-driven tests:
// Good
func TestParse(t *testing.T) {
tests := []struct {
name string
input string
want int
wantErr bool
}{
{name: "valid", input: "123", want: 123},
{name: "invalid", input: "abc", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Parse() = %v, want %v", got, tt.want)
}
})
}
}
Test names:
// Good
func TestParse(t *testing.T)
func TestParse_InvalidInput(t *testing.T)
func TestClient_Get_Success(t *testing.T)
// Bad
func TestParseFunction(t *testing.T)
func Test_Parse(t *testing.T)
Literal Formatting
Field names in structs:
// Good - specify field names for external types
r := csv.Reader{
Comma: ',',
Comment: '#',
FieldsPerRecord: 4,
}
// Good - field names optional for package-local types
okay := LocalType{42, "hello"}
Matching braces:
// Good
items := []*Item{
{Name: "foo"},
{Name: "bar"},
}
// Bad - misaligned braces
items := []*Item{
{Name: "foo"},
{Name: "bar"}}
Package Design
Package size:
- Not too large (thousands of lines in one package)
- Not too small (one type per package)
- Group related functionality
- Standard library is a good example
Avoid utility packages:
// Bad - vague package names
package util
package common
package helper
// Good - specific, focused packages
package cache
package auth
package stringutil
Common Patterns
Options Pattern
// Good - for optional configuration
type Options struct {
Timeout time.Duration
Retries int
}
func NewServer(addr string, opts Options) *Server
// Or using functional options
type Option func(*Server)
func WithTimeout(d time.Duration) Option {
return func(s *Server) {
s.timeout = d
}
}
func NewServer(addr string, opts ...Option) *Server
Constructor Pattern
// Good - New for single type in package
package widget
func New() *Widget
// Good - NewX for multiple types
package widget
func NewWidget() *Widget
func NewGizmo() *Gizmo
Cleanup Pattern
// Good - document cleanup requirements
// Open opens a file for reading.
// The caller must call Close when done.
func Open(name string) (*File, error)
// Good - defer for cleanup
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
Least Mechanism
Prefer simpler constructs:
- Use core language features first (channels, slices, maps, loops)
- Then standard library (http.Client, template engine)
- Finally, external dependencies (only if necessary)
// Good - use built-in
users := make(map[string]*User)
// Avoid - unless set operations are complex
import "github.com/deckarep/golang-set"
users := mapset.NewSet()
How I work
When you ask me to help with Go code, I will:
- Analyze the code for style violations and clarity issues
- Suggest specific improvements citing relevant style principles
- Rewrite code sections to match professional Go style
- Add proper documentation following godoc conventions
- Format imports, grouping, and structure correctly
- Simplify complex code while maintaining correctness
- Apply idiomatic Go patterns and best practices
I prioritize clarity, simplicity, and maintainability. The goal is code that is easy to read, understand, and maintain.
References
- Style Guide: https://google.github.io/styleguide/go/guide
- Style Decisions: https://google.github.io/styleguide/go/decisions
- Best Practices: https://google.github.io/styleguide/go/best-practices
- Effective Go: https://go.dev/doc/effective_go
- Code Review Comments: https://github.com/golang/go/wiki/CodeReviewComments
- Go Proverbs: https://go-proverbs.github.io/
More from the-perfect-developer/the-perfect-opencode
turso-libsql
This skill should be used when the user asks to "connect to Turso", "use libSQL", "set up a Turso database", "query Turso with TypeScript", or needs guidance on Turso Cloud, embedded replicas, or vector search with libSQL.
11alpinejs
This skill should be used when the user asks to "add Alpine.js", "create Alpine component", "use Alpine directives", "build interactive UI with Alpine", or needs guidance on Alpine.js development patterns and best practices.
10python-dependency-injection
This skill should be used when the user asks to "implement dependency injection in Python", "use the dependency-injector library", "decouple Python components", "write testable Python services", or needs guidance on Inversion of Control, DI containers, provider types, and wiring in Python applications.
3copilot-sdk
This skill should be used when the user asks to "integrate GitHub Copilot into an app", "use the Copilot SDK", "build a Copilot-powered agent", "embed Copilot in a service", or needs guidance on the GitHub Copilot SDK for Python, TypeScript, Go, or .NET.
3conventional-git-commit
This skill MUST be loaded on every git commit without exception. It should also be used when the user asks to "write a conventional commit", "format a commit message", "follow conventional commits spec", "create a semantic commit", "make a commit", "commit changes", or "git commit". Every commit message produced in this project MUST conform to this specification.
3agent-configuration
This skill should be used when the user asks to "configure agents", "create a custom agent", "set up agent permissions", "customize agent behavior", "switch agents", or needs guidance on OpenCode agent system.
3