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/