From ccfg-golang
This skill should be used when creating or editing go.mod, managing Go dependencies, configuring Go modules, or organizing Go packages and module boundaries.
How this skill is triggered — by the user, by Claude, or both
Slash command
/ccfg-golang:module-conventionsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill defines best practices for Go module management, dependency handling, package
This skill defines best practices for Go module management, dependency handling, package organization, and versioning following the Go modules system.
The module path in go.mod must be the full import path, typically matching the repository URL.
// CORRECT: Full repository path
module github.com/username/myproject
go 1.21
require (
github.com/pkg/errors v0.9.1
)
// WRONG: Incomplete or incorrect module path
module myproject // Missing domain and path
module example.com/myproject // Don't use example.com for real projects
For private repositories, use the full Git hosting path with authentication configured.
// CORRECT: Private repository module path
module github.com/mycompany/private-repo
go 1.21
# Configure Git for private repos
git config --global url."git@github.com:".insteadOf "https://github.com/"
# Or use GOPRIVATE environment variable
export GOPRIVATE=github.com/mycompany/*
# .netrc for private repos with HTTPS
machine github.com
login USERNAME
password TOKEN
Always specify the minimum Go version required by your module in go.mod.
// CORRECT: Explicit Go version
module github.com/username/myproject
go 1.21 // Minimum version required
require (
github.com/stretchr/testify v1.8.4
)
// WRONG: Missing or vague version
module github.com/username/myproject
// No go version specified - bad practice
Use .go-version file to pin the exact Go toolchain version for development.
# CORRECT: .go-version file
1.21.5
# Tools like goenv or asdf read .go-version
asdf install golang
goenv install
// go.mod specifies minimum
go 1.21
// .go-version specifies exact version for dev
// 1.21.5
Use the toolchain directive to specify the Go toolchain version.
// CORRECT: Toolchain directive
module github.com/username/myproject
go 1.21
toolchain go1.21.5
Always run go mod tidy to clean up dependencies and ensure go.mod and go.sum are in sync.
# CORRECT: Regular go mod tidy workflow
go mod tidy # Remove unused and add missing dependencies
go mod verify # Verify checksums
# In CI, verify go.mod is tidy
go mod tidy
git diff --exit-code go.mod go.sum || (echo "go.mod is not tidy" && exit 1)
# Taskfile.yml task
tasks:
tidy:
desc: Tidy and verify dependencies
cmds:
- go mod tidy
- go mod verify
- go mod download
Verify dependency checksums to ensure integrity.
# CORRECT: Verify dependencies
go mod verify
# WRONG: Skipping verification
go build # Builds without verification
# In CI pipeline
- name: Verify dependencies
run: |
go mod download
go mod verify
Use go mod why to understand why a dependency is required.
# CORRECT: Understanding dependency tree
go mod why github.com/pkg/errors
# Output shows dependency chain:
# github.com/username/myproject
# github.com/username/myproject/internal/service
# github.com/pkg/errors
# Find all dependencies of a package
go mod graph | grep github.com/pkg/errors
# Show dependency tree
go mod graph
Use go get to upgrade dependencies with version constraints.
# CORRECT: Controlled dependency upgrades
go get github.com/stretchr/testify@latest # Latest version
go get github.com/stretchr/testify@v1.8.4 # Specific version
go get github.com/stretchr/testify@v1 # Latest v1.x.x
go get -u ./... # Upgrade all dependencies
go get -u=patch ./... # Upgrade to latest patch versions
# WRONG: Uncontrolled upgrades
go get -u # Upgrades everything, can break builds
# Best practice: Test after upgrade
go get -u=patch ./...
go mod tidy
go test ./...
Use replace directives only for local development, never commit local filesystem paths.
// CORRECT: Replace for local development (don't commit)
module github.com/username/myproject
go 1.21
require (
github.com/username/library v1.2.3
)
// Uncomment for local development only
// replace github.com/username/library => ../library
// WRONG: Committed local replace directive
module github.com/username/myproject
go 1.21
replace github.com/username/library => /Users/john/projects/library // Never commit this!
Use replace to use a fork or specific commit of a dependency.
// CORRECT: Replace with fork
module github.com/username/myproject
go 1.21
require (
github.com/original/library v1.2.3
)
// Use fork with bug fix
replace github.com/original/library => github.com/username/library-fork v1.2.4-fix
# Replace with specific commit
go mod edit -replace=github.com/original/library=github.com/username/library-fork@commit-hash
Always document why a replace directive exists.
// CORRECT: Documented replace
module github.com/username/myproject
go 1.21
require (
github.com/problematic/library v1.0.0
)
// Replace with fork that fixes critical security issue CVE-2024-1234
// TODO: Remove when upstream merges fix (tracking issue: #123)
replace github.com/problematic/library => github.com/username/library-fixed v1.0.1-patched
Place all executable entry points in cmd/ directory with subdirectories for each binary.
# CORRECT: cmd structure for multiple binaries
myproject/
cmd/
server/
main.go
worker/
main.go
migrate/
main.go
internal/
service/
user.go
pkg/
client/
client.go
go.mod
// CORRECT: cmd/server/main.go
package main
import (
"log"
"myproject/internal/service"
)
func main() {
svc := service.New()
log.Fatal(svc.Start())
}
# WRONG: Binaries in root or mixed structure
myproject/
main.go # Don't put main in root for libraries
server.go
worker.go
Use internal/ directory for code that should not be importable by external modules.
# CORRECT: internal directory structure
myproject/
internal/
service/
user.go # Cannot be imported by external modules
repository/
postgres.go
middleware/
auth.go
pkg/
client/
client.go # Public API
go.mod
// CORRECT: Internal package
package service // In internal/service/user.go
// This package cannot be imported by modules outside myproject
type UserService struct {
repo Repository
}
// WRONG: Putting private code in pkg/
// pkg/internals/service.go
package internals // Don't use "internals" in pkg/
// Still importable by external modules, defeating the purpose
Use pkg/ directory for code intended to be imported by external modules.
# CORRECT: pkg for public API
myproject/
pkg/
client/
client.go # Public client library
types/
user.go # Public types
internal/
service/
impl.go # Private implementation
go.mod
// CORRECT: pkg/client/client.go
package client
// Client is the public API for external users
type Client struct {
baseURL string
}
// NewClient creates a new client instance
func NewClient(baseURL string) *Client {
return &Client{baseURL: baseURL}
}
Follow semantic versioning with v prefix for Git tags.
# CORRECT: Semantic versioning tags
git tag v1.0.0
git tag v1.1.0
git tag v1.1.1
git tag v2.0.0
git push origin v1.0.0
# WRONG: Missing v prefix or non-semver
git tag 1.0.0 # Missing 'v' prefix
git tag release-1 # Not semantic versioning
# Create and push version tag
git tag -a v1.2.3 -m "Release version 1.2.3"
git push origin v1.2.3
# List all version tags
git tag -l "v*"
For v2 and higher, add version suffix to module path.
// CORRECT: v2 module path
module github.com/username/myproject/v2
go 1.21
require (
github.com/stretchr/testify v1.8.4
)
// Import v2 module
import "github.com/username/myproject/v2/pkg/client"
# Create v2 tag
git tag v2.0.0
git push origin v2.0.0
// WRONG: v2 without path suffix
module github.com/username/myproject // Should be /v2
go 1.21
Use pre-release suffixes for unstable versions.
# CORRECT: Pre-release versions
git tag v1.0.0-alpha.1
git tag v1.0.0-beta.1
git tag v1.0.0-rc.1
git tag v1.0.0 # Final release
# Use pre-release in go.mod
require github.com/username/library v1.0.0-beta.1
Use Go module proxy instead of vendoring when possible.
# CORRECT: Configure module proxy
export GOPROXY=https://proxy.golang.org,direct
export GOSUMDB=sum.golang.org
# Private modules bypass proxy
export GOPRIVATE=github.com/mycompany/*
Use vendoring only when necessary for hermetic builds.
# CORRECT: Vendor when needed
go mod vendor
# Verify vendor is up to date
go mod vendor
git diff --exit-code vendor/
# Usually don't commit vendor/
vendor/
# But commit vendor/ if required for build reproducibility
# Build with vendor
go build -mod=vendor ./cmd/server
# WRONG: Vendoring by default
go mod vendor # Don't vendor unless necessary
Prefer single module per repository for simplicity.
# CORRECT: Single module (preferred)
myproject/
cmd/
internal/
pkg/
go.mod
# Use multi-module only with clear separation
monorepo/
service-a/
go.mod
cmd/
internal/
service-b/
go.mod
cmd/
internal/
Use go.work for local development of multiple modules.
# CORRECT: Initialize workspace
go work init ./service-a ./service-b
// go.work (don't commit to version control)
go 1.21
use (
./service-a
./service-b
)
# CORRECT: Ignore workspace file
go.work
go.work.sum
# Work with modules in workspace
cd service-a
go test ./... # Uses workspace configuration
# Sync workspace
go work sync
Indirect dependencies appear in go.mod when required by direct dependencies.
// CORRECT: Indirect dependencies marked
module github.com/username/myproject
go 1.21
require (
github.com/direct/dependency v1.2.3
)
require (
github.com/indirect/dependency v2.1.0 // indirect
)
# View all dependencies
go list -m all
# View dependency tree
go mod graph
Run go mod tidy to remove unused indirect dependencies.
# CORRECT: Remove unused dependencies
go mod tidy
# Check which module requires a dependency
go mod why github.com/indirect/dependency
Understand and configure Go module cache location.
# Default cache location
go env GOMODCACHE
# Output: /home/user/go/pkg/mod
# Set custom cache location
export GOMODCACHE=/custom/path
# Download all dependencies
go mod download
# Download specific module
go mod download github.com/stretchr/testify
# Clear module cache
go clean -modcache
Configure CI to cache module downloads for faster builds.
# CORRECT: GitHub Actions module caching
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
cache: true # Automatically caches modules
- name: Download dependencies
run: go mod download
# GitLab CI module caching
cache:
paths:
- .go/pkg/mod
before_script:
- export GOMODCACHE=$CI_PROJECT_DIR/.go/pkg/mod
- go mod download
Always commit go.sum for dependency verification.
# CORRECT: Don't ignore go.sum
# go.mod and go.sum should be committed
# WRONG: Ignoring go.sum
go.sum # Never add this to .gitignore!
# Verify go.sum is committed
git add go.mod go.sum
git commit -m "chore: update dependencies"
Configure checksum database for security.
# CORRECT: Use public checksum database
export GOSUMDB=sum.golang.org
# Disable for private modules
export GONOSUMDB=github.com/mycompany/*
# Verify all dependencies
go mod verify
Understand go get behavior in module mode.
# CORRECT: Module-aware go get
go get github.com/stretchr/testify@latest # Add or upgrade
go get github.com/stretchr/testify@v1.8.4 # Specific version
go get github.com/stretchr/testify@none # Remove dependency
# WRONG: Old GOPATH-style go get
export GO111MODULE=off # Don't disable modules
go get github.com/stretchr/testify # Unclear semantics
Use go install for installing command-line tools.
# CORRECT: Install tools with go install
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install mvdan.cc/gofumpt@latest
go install go.uber.org/mock/mockgen@latest
# WRONG: Using go get for tools
go get github.com/golangci/golangci-lint/cmd/golangci-lint # Old way
// Track tool dependencies in tools.go
//go:build tools
package tools
import (
_ "github.com/golangci/golangci-lint/cmd/golangci-lint"
_ "mvdan.cc/gofumpt"
_ "go.uber.org/mock/mockgen"
)
When creating a new Go module, follow this checklist.
# CORRECT: Initialize new module
mkdir myproject
cd myproject
# Initialize module
go mod init github.com/username/myproject
# Set Go version
go mod edit -go=1.21
# Create basic structure
mkdir -p cmd/myapp internal pkg
# Create .go-version
echo "1.21.5" > .go-version
# Create .gitignore
cat > .gitignore <<EOF
# Binaries
bin/
*.exe
# Go workspace
go.work
go.work.sum
# IDE
.idea/
.vscode/
*.swp
EOF
# Initialize git
git init
git add .
git commit -m "chore: initialize Go module"
Regular dependency maintenance workflow.
# CORRECT: Dependency update process
# 1. Check for updates
go list -u -m all
# 2. Update patch versions
go get -u=patch ./...
# 3. Test changes
go test ./...
# 4. Tidy dependencies
go mod tidy
# 5. Verify checksums
go mod verify
# 6. Check for vulnerabilities
govulncheck ./...
# 7. Commit changes
git add go.mod go.sum
git commit -m "chore: update dependencies"
This skill ensures proper Go module management, dependency handling, and package organization following the Go team's recommendations and community best practices.
npx claudepluginhub jsamuelsen11/claude-config --plugin ccfg-golangManages Go modules and dependencies: initializes projects, edits go.mod/go.sum, handles versioning/conflicts, sets up workspaces, troubleshoots errors.
Manages Go project dependencies: go.mod, upgrades, vulnerability scanning, conflict resolution, go.work workspaces, and automated update setup with Dependabot/Renovate.
Audits and updates Go module dependencies using go toolchain and govulncheck, with semver-aware patching and vulnerability checks.