Code Conventions
Error Handling
- •Use
errors.Wrap(err, "context")fromgithub.com/pkg/errors - •Use
status.Errorf(codes.NotFound, "message")for gRPC errors - •Use
connect.NewError(connect.Code, err)for Connect RPC errors - •Forbidden:
fmt.Errorf,ioutil.ReadDir
Imports
go
import (
// stdlib
"context"
"fmt"
"net/http"
"time"
// third-party
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/pkg/errors"
"connectrpc.com/connect"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
// local - use your project path
"github.com/usememos/memos/internal/profile"
"github.com/usememos/memos/server"
"github.com/usememos/memos/server/auth"
"github.com/usememos/memos/store"
)
- •Group: stdlib, third-party, local
- •Sort alphabetically within groups
- •Use
goimports -w .
Linting
- •Tool:
golangci-lint(.golangci.yaml) - •Formatter:
goimports - •Linters: revive, govet, staticcheck, misspell, gocritic, godot
Common Commands
bash
# Dev server go run ./cmd/memos --mode dev --port 8081 # Tests go test ./... go test -run TestName ./path/... go test -cover ./... # Lint & Format golangci-lint run goimports -w . # Proto cd proto && buf generate && buf lint
Workflows
Add API Endpoint
- •Create
proto/api/v1/{service}_service.proto- •Define request/response messages
- •Add RPC method with
google.api.httpannotation
- •Run
cd proto && buf generate - •Create
server/router/api/v1/{service}_service.go- •Implement service struct with store dependency
- •Implement Connect RPC handler methods
- •Register in
server/router/api/v1/v1.go- •Add to gRPC server:
v1pb.Register{Service}Server - •Add gRPC-Gateway handler:
{Service}HandlerFromEndpoint
- •Add to gRPC server:
- •Add to
acl_config.goif public endpoint - •Add frontend hook in
web/src/hooks/
Add Database Model
- •Create
store/migration/{driver}/{version}/NN__description.sql - •Update
store/migration/{driver}/LATEST.sql - •Update
store/driver.gointerface - •Implement in
store/db/{driver}/*.go - •Add to
store/store.goif caching needed - •Add model in
store/{model}.go
Run Tests Against Multiple Databases
bash
# SQLite (default) DRIVER=sqlite go test ./... # MySQL DRIVER=mysql DSN="user:pass@tcp(localhost:3306)/memos" go test ./... # PostgreSQL DRIVER=postgres DSN="postgres://user:pass@localhost:5432/memos?sslmode=disable" go test ./...