This document describes the standardized formatting conventions for Go source
files in the go-yaml project.
The reference implementation is yaml.go.
All non-test Go files should follow this section order:
- Copyright header (required)
- Package documentation (with TOC for files with 3+ sections)
- Imports
- Types (public first, then private)
- Constants (public first, then private)
- Variables (public first, then private)
- Functions (public first, then private)
Use a single divider comment only once per file, placed before the private functions section at the bottom:
// ----------------------------------------------------------------------------
// Private functions
// ----------------------------------------------------------------------------For files with 3+ major sections, include a TOC in the package documentation:
// Package yaml implements YAML support for Go.
//
// # Contents
//
// - Types: Node, Kind, Style, Marshaler, Unmarshaler
// - Functions: Marshal, Unmarshal, NewEncoder, NewDecoderEvery exported and unexported type, constant, variable, and function block needs a leading comment:
// NodeKind represents the kind of a YAML node.
type NodeKind uint8
// Node kinds.
const (
DocumentNode NodeKind = iota
SequenceNode
MappingNode
ScalarNode
AliasNode
)
// defaultMapType is the default type for unmarshaling maps.
var defaultMapType = reflect.TypeOf(map[string]any{})
// Marshal serializes the value provided into a YAML document.
func Marshal(v any) ([]byte, error) {- Start comments with the name of the thing being documented
- Use complete sentences
- Wrap at 80 columns
- For grouped declarations (type blocks, const blocks), one comment for the block is sufficient
Related types can be grouped in a single type () block with one leading
comment:
// Marshaler and Unmarshaler interfaces for custom YAML handling.
type (
Marshaler interface {
MarshalYAML() (any, error)
}
Unmarshaler interface {
UnmarshalYAML(node *Node) error
}
)Test files (*_test.go) follow different rules:
- Keep the standard Go test file interleaved structure
- Do NOT reorder into Types/Constants/Variables/Functions sections
- Tests naturally interleave helper types/functions with their tests
- Helper functions: Add comments describing their purpose
- Test types: Add comments for standalone type definitions
- Test data vars: Can remain without comments (self-documenting table names)
Example:
// errReader is a test io.Reader that always returns an error.
type errReader struct{}
func (errReader) Read([]byte) (int, error) {
return 0, errors.New("some read error")
}
// runDecodeTest runs a single decode test case from the data-driven test
// suite.
func runDecodeTest(t *testing.T, tc map[string]any) {
t.Helper()
// ...
}After each file modification:
make check # Ensure all tests passFor each source file:
- Read the entire file to understand its structure
- Identify sections: types, constants, variables, functions
- Check for missing comments on any declarations
- Reorder if needed: Types → Constants → Variables → Functions
- Add divider before private functions (if file has private functions)
- Add TOC to package doc (if file has 3+ sections)
- Run verification commands
For each test file:
- Read the entire file
- Identify types and helper functions without comments
- Add comments to standalone types and helper functions
- Do NOT reorder - keep interleaved structure
- Run verification commands