Loading...
Loading...
Apply Go style guide conventions to code
npx skill4agent add the-perfect-developer/the-perfect-opencode gogofmtgofmt -w .MixedCapsmixedCaps// Good
package creditcard
package tabwriter
package oauth2
// Bad
package credit_card
package tabWriter
package oAuth2// Good - avoid repetition with package name
package yamlconfig
func Parse(input string) (*Config, error)
// Bad - repetitive
func ParseYAMLConfig(input string) (*Config, error)icdbuserCountdatabaseConnectionusersuserSlice// Good
const MaxPacketSize = 512
const ExecuteBit = 1 << iota
// Bad
const MAX_PACKET_SIZE = 512
const kMaxBufferSize = 1024// Good
func ServeHTTP(w http.ResponseWriter, r *http.Request)
func ProcessXMLAPI() error
var userID string
// Bad
func ServeHttp()
func ProcessXmlApi()
var userId string// 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)// Package math provides basic constants and mathematical functions.
//
// This package does not guarantee bit-identical results across architectures.
package math// 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// 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"
)// 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"
)// Bad
import . "foo"
// Good
import "foo"// 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
}// Good - lowercase, no punctuation
err := fmt.Errorf("something bad happened")
// Bad
err := fmt.Errorf("Something bad happened.")// Good
if err := doSomething(); err != nil {
return fmt.Errorf("failed to do something: %w", err)
}
// Bad - ignoring errors
_ = doSomething()// Good
if err != nil {
// error handling
return err
}
// normal code
// Bad - avoid else after error
if err != nil {
// error handling
} else {
// normal code
}// 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)// 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
}// Good
func (c *Config) WriteTo(w io.Writer) (int64, error)
// Bad - repetitive
func (c *Config) WriteConfigTo(w io.Writer) (int64, error)// 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
// ...
}// Good - single method interface
type Reader interface {
Read(p []byte) (n int, err error)
}
// Good - composed interfaces
type ReadWriter interface {
Reader
Writer
}// Good
func Process(r io.Reader) (*Result, error)
// Avoid unless necessary
func Process(r *os.File) (*Result, error)// 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 { ... }// 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// 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)
}
})
}
}// 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)// 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"}// Good
items := []*Item{
{Name: "foo"},
{Name: "bar"},
}
// Bad - misaligned braces
items := []*Item{
{Name: "foo"},
{Name: "bar"}}// Bad - vague package names
package util
package common
package helper
// Good - specific, focused packages
package cache
package auth
package stringutil// 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// 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// 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()// Good - use built-in
users := make(map[string]*User)
// Avoid - unless set operations are complex
import "github.com/deckarep/golang-set"
users := mapset.NewSet()