# Golang Skill

> Write clean and readable code in golang, following Golang best practices and design patterns.

- Skill: `thealish/golang-skill` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add thealish/golang-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/thealish/golang-skill/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: Complete terms in LICENSE.txt
- Author: thealish (https://skillmd.com/u/thealish)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/thealish/golang-skill

---


These are the instructions for writing clean, maintainable and efficient code in golang.

Naming conventions:
- Use camelCase for unexported identifiers
- Use PascalCase for exported identifiers
- Package names should be short, lowercase and descriptive. Good: `net/http`, `image/png`, `testframework`, Bad: `kafka_topic_manager`, `helper_util`
- For single method interfaces use -er suffix. Good: `Reader`, `Writer`, `Closer`, Bad: `ReadInterface`, `IRead`, `ReadIface`

Common best practices:
- Do not have multiple nested if statements, if possible extract them to switch statement
- Try to avoid nested else if statement
- Always use `context.Context` for IO operations

Project structure:
- Avoid creating generic packages like `utils`, `helpers`, `common`
- Use internal/ for internal packages which should not be exposed
- For large applications that require multiple main files use cmd/ folders. Example: cmd/api/main.go, cmd/cli/main.go
- For sub packages use pkg/ folder.
- Do not have very large files, try to split them into smaller files by domain

Error handling:
- Never skip error checking
- Never use panic unless user explicitly asked for it
- When wrapping error or adding context using fmt.Errorf do not expose implementation details
- Avoid nesting, always check errors first

Bad:

```go
func (g *Gopher) WriteTo(w io.Writer) (size int64, err error) {
    err = binary.Write(w, binary.LittleEndian, int32(len(g.Name)))
    if err == nil {
        size += 4
        var n int
        n, err = w.Write([]byte(g.Name))
        size += int64(n)
        if err == nil {
            err = binary.Write(w, binary.LittleEndian, int64(g.AgeYears))
            if err == nil {
                size += 4
            }
            return
        }
        return
    }
    return
}
```

Good:

```go
func (g *Gopher) WriteTo(w io.Writer) (size int64, err error) {
    err = binary.Write(w, binary.LittleEndian, int32(len(g.Name)))
    if err != nil {
        return
    }
    size += 4
    n, err := w.Write([]byte(g.Name))
    size += int64(n)
    if err != nil {
        return
    }
    err = binary.Write(w, binary.LittleEndian, int64(g.AgeYears))
    if err == nil {
        size += 4
    }
    return
}
```

Concurrency best practices:
- Use WaitGroup if you want to wait for multiple goroutines to finish
- Check ctx.Done() to check if context is cancelled to avoid doing unnecessary work
