# Go Functions

> Use when organizing functions within a Go file, formatting function signatures, designing return values, or following Printf-style naming conventions. Also use when a user is adding or refactoring any Go function, even if they don't mention function design or signature formatting. Does not cover functional options constructors.

- Skill: `pngdeity/go-functions` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add pngdeity/go-functions`
- Raw SKILL.md: https://api.skillmd.com/api/skills/pngdeity/go-functions/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: pngdeity (https://skillmd.com/u/pngdeity)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/pngdeity/go-functions

---


# Go Function Design

## Function Grouping and Ordering

Organize functions in a file by these rules:

1. Functions sorted in **rough call order**
2. Functions **grouped by receiver**
3. **Exported** functions appear first, after `struct`/`const`/`var` definitions
4. `NewXxx`/`newXxx` constructors appear right after the type definition
5. Plain utility functions appear toward the end of the file

```go
type something struct{ ... }

func newSomething() *something { return &something{} }

func (s *something) Cost() int { return calcCost(s.weights) }

func (s *something) Stop() { ... }

func calcCost(n []int) int { ... }
```

---

## Function Signatures

> Read [references/SIGNATURES.md](references/SIGNATURES.md) when formatting multi-line signatures, wrapping return values, shortening call sites, or replacing naked bool parameters with custom types.

Keep the signature on a single line when possible. When it must wrap, put **all
arguments on their own lines** with a trailing comma:

```go
func (r *SomeType) SomeLongFunctionName(
    foo1, foo2, foo3 string,
    foo4, foo5, foo6 int,
) {
    foo7 := bar(foo1)
}
```

Add `/* name */` comments for ambiguous arguments, or better yet, replace naked
`bool` parameters with custom types.

---

## Pointers to Interfaces

You almost never need a pointer to an interface. Pass interfaces as values — the
underlying data can still be a pointer.

```go
// Bad: pointer to interface
func process(r *io.Reader) { ... }

// Good: pass the interface value
func process(r io.Reader) { ... }
```

---

## Printf and Stringer

> Read [references/PRINTF-STRINGER.md](references/PRINTF-STRINGER.md) when using Printf verbs beyond %v/%s/%d, implementing fmt.Stringer or fmt.GoStringer, writing custom Format() methods, or debugging infinite recursion in String() methods.

### Printf-style Function Names

Functions that accept a format string should end in `f` for `go vet` support.
Declare format strings as `const` when used outside `Printf` calls.

Prefer `%q` over `%s` with manual quoting when formatting strings for logging
or error messages — it safely escapes special characters and wraps in quotes:

```go
return fmt.Errorf("unknown key %q", key) // produces: unknown key "foo\nbar"
```

---

## Quick Reference

| Topic | Rule |
|-------|------|
| File ordering | Type -> constructor -> exported -> unexported -> utils |
| Signature wrapping | All args on own lines with trailing comma |
| Naked parameters | Add `/* name */` comments or use custom types |
| Pointers to interfaces | Almost never needed; pass interfaces by value |
| Printf function names | End with `f` for `go vet` support |

