From oape
Ensures all generated Go code follows best practices from the official Effective Go documentation and Go community standards.
How this skill is triggered — by the user, by Claude, or both
Slash command
/oape:effective-goThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Ensures all generated Go code follows best practices from the official Effective Go documentation and Go community standards.
Ensures all generated Go code follows best practices from the official Effective Go documentation and Go community standards.
This skill provides guidelines for writing idiomatic, clean, and maintainable Go code. It is applied whenever generating Go code (types, controllers, tests) to ensure consistency and quality.
generate-types)generate-controller)generate-tests)Rule: Always format code with gofmt standards.
// GOOD: Proper formatting
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx)
logger.Info("Starting reconciliation")
return ctrl.Result{}, nil
}
// BAD: Inconsistent formatting
func (r *Reconciler) Reconcile(ctx context.Context,req ctrl.Request) (ctrl.Result,error) {
logger := log.FromContext(ctx)
logger.Info("Starting reconciliation")
return ctrl.Result{},nil
}
Rules:
MixedCaps for exported identifiers (public)mixedCaps for unexported identifiers (private)HTTP, URL, ID (not Http, Url, Id)// GOOD: Proper naming
type IngressController struct {} // Exported, MixedCaps
type ingressConfig struct {} // Unexported, mixedCaps
func (r *Reconciler) GetHTTPClient() {} // Acronym all caps
var userID string // ID not Id
// BAD: Improper naming
type Ingress_Controller struct {} // No underscores
type IngressConfig struct {} // Should be unexported if internal
func (r *Reconciler) GetHttpClient() {} // Http should be HTTP
var userId string // Id should be ID
Rules:
fmt.Errorf("context: %w", err)_// GOOD: Proper error handling
func (r *Reconciler) reconcile(ctx context.Context, obj *v1.Resource) error {
if err := r.validateSpec(obj); err != nil {
return fmt.Errorf("spec validation failed: %w", err)
}
if err := r.createConfigMap(ctx, obj); err != nil {
return fmt.Errorf("failed to create ConfigMap: %w", err)
}
return nil
}
// BAD: Poor error handling
func (r *Reconciler) reconcile(ctx context.Context, obj *v1.Resource) {
r.validateSpec(obj) // Error ignored!
err := r.createConfigMap(ctx, obj)
if err != nil {
panic(err) // Don't panic!
}
}
Rules:
// GOOD: Proper error messages
return fmt.Errorf("failed to create ConfigMap %s: %w", name, err)
return fmt.Errorf("spec.replicas must be positive, got %d", replicas)
// BAD: Poor error messages
return fmt.Errorf("Error creating ConfigMap.") // Uppercase, punctuation
return fmt.Errorf("failed") // Not specific
return errors.New("something went wrong") // Vague
Rules:
// GOOD: Proper documentation
// Reconciler manages the lifecycle of Foo resources.
// It creates and updates dependent resources based on the Foo spec.
type Reconciler struct {
client.Client
Scheme *runtime.Scheme
}
// Reconcile performs a single reconciliation loop for a Foo resource.
// It returns an error if the reconciliation fails.
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
// ...
}
// DefaultRequeueInterval is the default interval between reconciliations.
const DefaultRequeueInterval = 30 * time.Second
// BAD: Poor or missing documentation
type Reconciler struct { // No documentation
client.Client
}
// reconciles foo // Doesn't start with name, incomplete sentence
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
Rules:
-er suffix// GOOD: Small, focused interface
type StatusUpdater interface {
UpdateStatus(ctx context.Context, obj client.Object) error
}
// GOOD: Accept interface, return concrete
func NewReconciler(client client.Client) *Reconciler {
return &Reconciler{Client: client}
}
// BAD: Large interface
type ResourceManager interface {
Create(ctx context.Context, obj client.Object) error
Update(ctx context.Context, obj client.Object) error
Delete(ctx context.Context, obj client.Object) error
Get(ctx context.Context, key types.NamespacedName, obj client.Object) error
List(ctx context.Context, list client.ObjectList) error
Patch(ctx context.Context, obj client.Object, patch client.Patch) error
// ... too many methods
}
Rules:
sync.Mutex only when channels are impractical// GOOD: Respect context cancellation
func (r *Reconciler) reconcile(ctx context.Context, obj *v1.Resource) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
// Continue with reconciliation
return r.doWork(ctx, obj)
}
// GOOD: Use channels for coordination
results := make(chan Result, len(items))
for _, item := range items {
go func(item Item) {
results <- process(item)
}(item)
}
Rules:
util, common, misc package names// GOOD: Clear package names
package controller
package reconciler
package status
// BAD: Poor package names
package controller_utils // No underscores
package common // Too vague
package myPackage // No mixed case
Rules:
// GOOD: Properly organized imports
import (
"context"
"fmt"
"time"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
configv1 "github.com/openshift/api/config/v1"
"github.com/myorg/myoperator/internal/controller"
)
// BAD: Unorganized imports
import (
"github.com/myorg/myoperator/internal/controller"
"context"
corev1 "k8s.io/api/core/v1"
"fmt"
"sigs.k8s.io/controller-runtime/pkg/client"
)
Rules:
:=) inside functionsvar for package-level variables or zero values// GOOD: Appropriate declarations
const (
DefaultTimeout = 30 * time.Second
MaxRetries = 3
)
var (
ErrNotFound = errors.New("resource not found")
ErrInvalidSpec = errors.New("invalid spec")
)
func (r *Reconciler) reconcile(ctx context.Context) error {
logger := log.FromContext(ctx) // Short declaration
instance := &v1.Resource{} // Short declaration
var result ctrl.Result // Zero value needed
return nil
}
// BAD: Inconsistent declarations
func (r *Reconciler) reconcile(ctx context.Context) error {
var logger = log.FromContext(ctx) // Use := instead
instance := new(v1.Resource) // Use &v1.Resource{} instead
}
Rules:
this or self// GOOD: Short, consistent receivers
func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {}
func (r *Reconciler) reconcileDelete(ctx context.Context, obj *v1.Resource) error {}
func (r *Reconciler) setCondition(obj *v1.Resource, condition metav1.Condition) {}
// BAD: Inconsistent or long receivers
func (reconciler *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) {}
func (r *Reconciler) reconcileDelete(ctx context.Context, obj *v1.Resource) {}
func (this *Reconciler) setCondition(obj *v1.Resource, condition metav1.Condition) {}
Rules:
// GOOD: Zero value is useful
type Config struct {
Timeout time.Duration // Zero means no timeout
Replicas int // Zero means default
}
cfg := Config{} // Usable immediately
// GOOD: Check for zero value
if cfg.Timeout == 0 {
cfg.Timeout = DefaultTimeout
}
This skill is referenced by:
generate-types - When generating API type definitionsgenerate-controller - When generating controller codegenerate-tests - When generating test codeAll Go code generation MUST follow these guidelines.
npx claudepluginhub shivprakashmuley/oape-ai-e2e --plugin oape3plugins reuse this skill
First indexed Jun 9, 2026
Applies Go best practices, idioms, and conventions from Effective Go guide for writing, reviewing, and refactoring idiomatic Go code.
Guides Go code with pedantic best practices: error wrapping using fmt.Errorf/%w, interface design (accept interfaces return structs), package naming, struct field ordering, receiver naming, golangci-lint config.
Provides idiomatic Go patterns and best practices for building robust, maintainable applications. Covers error handling, interface design, and zero-value usage.