Go programming language. Covers goroutines, channels, interfaces, error handling, and modules. Use for building concurrent, high-performance backend services. USE WHEN: user mentions "go", "golang", "goroutines", "channels", asks about "concurrency", "select statement", "interfaces", "error handling", "go modules" DO NOT USE FOR: reviewing existing Go code - use `review/go`, which covers the defects the compiler and linters do not report DO NOT USE FOR: Gin/Fiber/Echo frameworks - use framework-specific skills DO NOT USE FOR: GORM - use ORM-specific skill DO NOT USE FOR: gRPC - use API design skills

GitHub
Install command
npx skhub add claude-dev-suite/go
Markdown
SKILL.md

Go Core Knowledge

Full Reference: See advanced.md for concurrency patterns (worker pool, semaphore, fan-out/fan-in), production readiness, structured logging, graceful shutdown, context usage, health checks, testing patterns, HTTP client best practices, and database connection pooling.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: go for comprehensive documentation.

Goroutines and Concurrency

Basic Goroutine

func sayHello(name string) {
    fmt.Printf("Hello, %s!\n", name)
}

func main() {
    go sayHello("World")  // Run concurrently
    time.Sleep(100 * time.Millisecond)
}

Core Principle

"Do not communicate by sharing memory; instead, share memory by communicating."


Channels

Unbuffered Channel

c := make(chan int)  // Unbuffered channel

go func() {
    result := compute()
    c <- result  // Send - blocks until received
}()

value := <-c  // Receive - blocks until sent

Buffered Channel

ch := make(chan int, 10)  // Buffer size 10

ch <- 1  // Non-blocking (if buffer not full)
ch <- 2

value := <-ch

Channel Direction

func send(ch chan<- int, value int) { ch <- value }   // Send-only
func receive(ch <-chan int) int { return <-ch }       // Receive-only

Select Statement

select {
case msg := <-ch1:
    fmt.Println("Received from ch1:", msg)
case ch2 <- value:
    fmt.Println("Sent to ch2")
case <-time.After(5 * time.Second):
    fmt.Println("Timeout")
default:
    fmt.Println("No communication ready")
}

Interfaces

Interface Definition

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

// Embedded interfaces
type ReadWriter interface {
    Reader
    Writer
}

Implicit Implementation

type MyReader struct {
    data []byte
    pos  int
}

// No "implements" keyword needed
func (r *MyReader) Read(p []byte) (n int, err error) {
    if r.pos >= len(r.data) {
        return 0, io.EOF
    }
    n = copy(p, r.data[r.pos:])
    r.pos += n
    return n, nil
}

Type Assertion and Switch

// Safe check
str, ok := value.(string)
if ok {
    fmt.Printf("string value: %q\n", str)
}

// Type switch
switch v := value.(type) {
case bool:
    fmt.Printf("boolean %t\n", v)
case int:
    fmt.Printf("integer %d\n", v)
default:
    fmt.Printf("unexpected type %T\n", v)
}

Error Handling

Standard Pattern

func doSomething() error {
    if err := step1(); err != nil {
        return fmt.Errorf("step1 failed: %w", err)
    }
    return nil
}

Custom Error Types

type PathError struct {
    Op   string
    Path string
    Err  error
}

func (e *PathError) Error() string {
    return e.Op + " " + e.Path + ": " + e.Err.Error()
}

func (e *PathError) Unwrap() error {
    return e.Err
}

Error Wrapping (Go 1.13+)

// Wrap error with context
return fmt.Errorf("failed to open config: %w", err)

// Check wrapped errors
if errors.Is(err, os.ErrNotExist) {
    // Handle file not found
}

// Get underlying error type
var pathErr *os.PathError
if errors.As(err, &pathErr) {
    fmt.Println("Path:", pathErr.Path)
}

Structs and Methods

type User struct {
    ID    int64  `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

// Value receiver - cannot modify original
func (u User) FullName() string { return u.Name }

// Pointer receiver - can modify original
func (u *User) SetName(name string) { u.Name = name }

// Constructor pattern
func NewUser(name, email string) *User {
    return &User{
        ID:    generateID(),
        Name:  name,
        Email: email,
    }
}

Generics (Go 1.18+)

func Map[T, U any](slice []T, fn func(T) U) []U {
    result := make([]U, len(slice))
    for i, v := range slice {
        result[i] = fn(v)
    }
    return result
}

type Stack[T any] struct {
    items []T
}

func (s *Stack[T]) Push(item T) {
    s.items = append(s.items, item)
}

// Type constraints
type Number interface {
    ~int | ~int32 | ~int64 | ~float32 | ~float64
}

func Sum[T Number](numbers []T) T {
    var sum T
    for _, n := range numbers {
        sum += n
    }
    return sum
}

Modules

go.mod

module github.com/user/myproject

go 1.21

require (
    github.com/gin-gonic/gin v1.9.1
)

Common Commands

go mod init github.com/user/project  # Initialize module
go mod tidy                          # Add missing, remove unused
go get package@version               # Add/update dependency
go list -m all                       # List all dependencies

Project Structure

myproject/
├── cmd/
│   └── server/
│       └── main.go        # Entry point
├── internal/              # Private packages
│   ├── handler/
│   ├── service/
│   └── repository/
├── pkg/                   # Public packages
├── go.mod
└── Makefile

When NOT to Use This Skill

ScenarioUse Instead
Gin/Fiber/Echo specificsFramework-specific skills
GORM operationsORM-specific skill
gRPC service definitionapi-design-grpc skill
Testing specificstesting-go skill

Anti-Patterns

Anti-PatternWhy It's BadCorrect Approach
Not closing channelsGoroutine leaksAlways close when done
Ignoring errorsSilent failuresCheck every error
Goroutine without contextCan't cancelPass context.Context
Not using defer for cleanupResource leaksAlways defer cleanup
Panic in productionProcess crashesReturn errors
Empty interface everywhereLoses type safetyUse generics (1.18+)
Copying mutexesUndefined behaviorPass by pointer

Quick Troubleshooting

IssueCauseSolution
"all goroutines are asleep - deadlock!"Channel deadlockCheck send/receive balance
"close of closed channel"Closing twiceUse sync.Once
"concurrent map writes"Race conditionUse sync.Map or mutex
"context deadline exceeded"Timeout reachedIncrease timeout or optimize
"assignment to entry in nil map"Map not initializedInitialize with make()
"nil pointer dereference"Accessing nilCheck for nil before use

Reference Documentation

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/languages/go

Default branch

main

Latest commit

9496306

Tree SHA

fe4e2f1