This is the Flare Go style guide. Follow these conventions when writing Go code for Flare projects. Where these rules conflict with general Go conventions, these rules take precedence.
Command golangci-lint run must be used before the end of each edit and issues must be resolved.
A .golangci.yml config is provided in this directory — use it as a template for new projects.
When ignoring a linter, always include a reason:
//nolint:<linterName>,<otherLinter> // reason for ignoringPlace it directly above a block (package, struct, function) or inline on a single line.
- Use the shortest name that sufficiently describes the item. Omit words clear from context.
- The smaller the scope, the shorter the name. Common abbreviations (
db,cfg) are fine. - Names should describe purpose, not value.
- Only camelCase and PascalCase are allowed. Never use
_in any identifier, including test function names. - For initialisms and acronyms, all letters must have the same case:
ID,URL,HTTP— notId,Url,Http.
- Do not use
Getas a prefix. UseCompute,Fetch, or a descriptive verb — and only when the operation takes meaningful time. For simple accessors, just name the concept directly. - Receiver variables must be very short (one or two letters) and consistent across all methods of the same type.
All Flare module names must match their public repo path:
github.com/flare-foundation/<name-of-the-repo>
- Package name and its folder name must be identical — no underscores in folder names (except
_testpackages). - Avoid generic names like
utilsfor exported packages. - Name package contents with the package name in mind, and vice versa — the full reference is
package.Name, so avoid redundancy.
pkg/— exported packagesinternal/— unexported packagescmd/— executables- Tests and test helpers go in
_test.gofiles or/internal, never exported.
- Prefer
errors.Newoverfmt.Errorfwhen there are no format arguments. - Use
%wfor error wrapping,%vfor error formatting in log messages. - Error types end with
Errororerror; error variables start withErr. errors.New("text")and anothererrors.New("text")are distinct errors. Use package-level variables when code needs to match on a specific error.- Never expose internal error details through a server API.
- Always handle errors. If intentionally ignoring one, document it:
//nolint:errcheck,gosec // reason for ignoring- Doc comments are complete sentences starting with the name of the item they describe.
- Describe what the item does, not how. Only include "how" if it is not obvious from the code.
- Use the logger from
go-flare-common. - Exported code must not log directly. If logging is needed, accept a logger as an interface and let the caller configure it.
Prefer the standard library. Add external dependencies only when necessary.
go-flare-common is the shared library across Flare Go projects. It includes:
- Logging utilities
- abigen contract bindings
- Common helpers reused across repos
All changes to this repo must be backwards compatible and well tested.
These are largely interchangeable in the Flare ecosystem. Prefer them for:
abi— working with ABIscrypto— Ethereum-ecosystem cryptographycommon— general helpershexutil— marshaling of byte slices
Use abigen to generate type-safe Go bindings from smart contract ABIs.
Standard practice: create a directory named after the package (derived from the contract name). Place the ABI file and a Go file with a go:generate directive there:
//go:generate abigen --abi=neki.abi --pkg=neki --type Neki --out=autogen.go
package nekiAll bindings can then be regenerated with:
go generate ./...- Use testify:
requirefor fatal assertions,assertfor non-fatal,mockfor mocking. - When a unit test needs an external database (SQL, Redis, …), use an in-memory mock instead of a real database.
- Tests must be independent — they must pass in any order and potentially in parallel.
- Use
t.Helper()in auxiliary test functions. - Prefer table-driven tests for cases with multiple inputs.
Never use raw integers for durations. Always multiply by the time unit:
x = 12 * time.Second // correct
x = 12 // wrongWhen a variable is declared outside a block and set inside using := alongside an error return, the outer variable is silently shadowed:
// Wrong — outer x is never set
var x int
if something {
x, err := f() // x here is a new variable scoped to the if block
}
// Correct
var x int
if something {
var err error
x, err = f()
}When the final length is known, initialize with capacity to avoid reallocations:
x := make([]T, 0, n) // then append
// or
x := make([]T, n) // then assign by indexTo assert at compile time that *X implements interface Y:
var _ Y = &X{}Place this near the type definition. A missing method causes a compile error immediately.