This is the SkyWalking BanyanDB project - a distributed time-series database written in Go. Follow these strict coding standards when generating or modifying Go code.
- Maximum line length: 170 characters
- Variable shadowing prevention (govet shadow enabled)
- Import aliases for specific packages (importas settings)
- Error handling patterns (errcheck, errorlint, errname)
- Code style and conventions (gosimple, staticcheck, stylecheck)
- Security considerations (gosec)
- Documentation standards (godot scope: toplevel)
Follow the sections order:
- Standard library imports
- Default imports
- github.com/apache/skywalking-banyandb/ prefix imports
Use these specific aliases for protobuf packages:
- github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v1 → commonv1
- github.com/apache/skywalking-banyandb/api/proto/banyandb/database/v1 → databasev1
- github.com/apache/skywalking-banyandb/api/proto/banyandb/model/v1 → modelv1
- github.com/apache/skywalking-banyandb/api/proto/banyandb/property/v1 → propertyv1
- github.com/apache/skywalking-banyandb/api/proto/banyandb/measure/v1 → measurev1
- github.com/apache/skywalking-banyandb/api/proto/banyandb/stream/v1 → streamv1
- github.com/apache/skywalking-banyandb/api/proto/banyandb/cluster/v1 → clusterv1
- github.com/apache/skywalking-banyandb/api/proto/banyandb/trace/v1 → tracev1
- github.com/apache/skywalking-banyandb/pkg/pb/v1 → pbv1
- Always check errors immediately after function calls
- Use descriptive error variable names to avoid shadowing
- Follow the errname convention for error types
- Use errorlint for consistent error handling
- Wrap errors with context using fmt.Errorf and %w verb
- NEVER shadow variables in the same scope
- Use unique variable names in nested scopes
- Be especially careful with common variable names like 'err', 'ctx', 'v', 'i', 'n', etc.
- When using range loops, use descriptive variable names instead of single letters
- In if statements with variable declarations, ensure the variable name doesn't conflict with outer scope
- Use gocritic enabled checks for code quality
- Follow exhaustive switch/map patterns
- Use proper field alignment (govet fieldalignment)
- Avoid unnecessary conversions (unconvert)
- Use standard library variables when available (usestdlibvars)
- Follow whitespace rules (whitespace linter)
- Keep code compact - group related code together with minimal blank lines
- Follow gosec security guidelines
- Be aware of integer overflow conversions (G115 excluded in config)
- Add top-level comments for exported functions and types (godot scope: toplevel)
- Follow docStub patterns for documentation
- Use proper sentence structure and punctuation
- Describe what the function does, not how it does it
- Minimize comments - add only when necessary for exported functions/types or complex logic
- Use goconst for repeated string literals (min-occurrences: 4)
- Avoid magic numbers, use named constants
- Keep cyclomatic complexity low (gocyclo)
- Avoid deeply nested structures
- Use proper abstraction levels
- Use descriptive names for variables, especially in nested scopes
- Follow Go naming conventions
- Use proper package naming
- Follow the project's specific naming patterns
- Follow proper test naming conventions
- Use appropriate test helpers
- Follow the project's testing patterns
The following file patterns are excluded from linting:
- *.pb.go (protobuf generated files)
- *.pb.gw.go (protobuf gateway files)
- *.gen.go (generated files)
- *_mock.go (mock files)
- *_test.go files have relaxed errcheck rules
if err := someFunc(); err != nil {
if v := someValue(); v != nil {
for _, v := range items {
for i, v := range items {
switch v := someValue(); v {
defer func() { if err := cleanup(); err != nil {import (
"fmt"
"github.com/apache/skywalking-banyandb/pkg/something"
"os"
)someFunc() // ignoring error
if err != nil {
return
}if x == true {
if x == false {
if x != nil && x.y == true {// Function does something
// This function does something
x := 1 // set x to 1
for _, v := range items { // iterate over items
doSomething(v) // process item
}
func (r *Request) Data() []byte { // return data
return r.data
}if resultErr := someFunc(); resultErr != nil {
if item := someValue(); item != nil {
for _, item := range items {
for idx, item := range items {
switch value := someValue(); value {
defer func() { if cleanupErr := cleanup(); cleanupErr != nil {import (
"fmt"
"os"
"github.com/apache/skywalking-banyandb/pkg/something"
)if err := someFunc(); err != nil {
return fmt.Errorf("failed to do something: %w", err)
}if x {
if !x {
if x != nil && x.y {// ProcessData processes the given data and returns the result.
func ProcessData(ctx context.Context, data []byte) ([]byte, error) {
if len(data) == 0 {
return nil, fmt.Errorf("data cannot be empty")
}
for idx, item := range data {
if processErr := processItem(ctx, item); processErr != nil {
return nil, fmt.Errorf("failed to process item at index %d: %w", idx, processErr)
}
}
return finalizeProcessing(ctx, data)
}
// Data returns the request body.
func (r *Request) Data() []byte {
return r.data
}- Check for existing variable names in the current scope before declaring new ones
- Use descriptive variable names to avoid shadowing
- Organize imports according to "IMPORT ORGANIZATION" sections
- Use proper import aliases for the project's protobuf packages
- Follow error handling patterns with proper error wrapping
- Add appropriate documentation for exported functions and types
- Keep line length under 170 characters
- Use gofumpt formatting style
package example
import (
"context"
"fmt"
"time"
commonv1 "github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v1"
"github.com/apache/skywalking-banyandb/pkg/logger"
)
// ProcessData processes the given data and returns the result.
func ProcessData(ctx context.Context, data []byte) ([]byte, error) {
if len(data) == 0 {
return nil, fmt.Errorf("data cannot be empty")
}
for idx, item := range data {
if processErr := processItem(ctx, item); processErr != nil {
return nil, fmt.Errorf("failed to process item at index %d: %w", idx, processErr)
}
}
result, err := finalizeProcessing(ctx, data)
if err != nil {
return nil, fmt.Errorf("failed to finalize processing: %w", err)
}
return result, nil
}package example
import (
"fmt"
"github.com/apache/skywalking-banyandb/api/proto/banyandb/common/v1" // wrong alias
"os"
)
func ProcessData(ctx context.Context, data []byte) ([]byte, error) {
for _, v := range data {
if err := processItem(ctx, v); err != nil { // 'err' shadows outer scope
return err
}
for i, v := range v.SubItems { // 'v' shadows outer 'v'
if err := processSubItem(v); err != nil { // 'err' shadows outer 'err'
return err
}
}
}
return nil
}err, error, ctx, context, v, value, i, idx, index, n, num, count, size, len, length, k, key, val, result, res, data, item, obj, object, msg, message, resp, response, req, request, client, conn, connection
When dealing with nested scopes, use these naming patterns:
- Outer scope: 'err', 'ctx', 'v', 'i'
- Inner scope: 'innerErr', 'innerCtx', 'item', 'idx'
- Deep nested: 'deepErr', 'deepCtx', 'subItem', 'subIdx'
- Or use descriptive prefixes: 'processErr', 'validateErr', 'parseErr'