| name | go-project-conventions |
| description | Code conventions including error handling, imports, linting, common commands, and workflows |
Code Conventions
Error Handling
- Use
errors.Wrap(err, "context") from github.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
import (
"context"
"fmt"
"net/http"
"time"
"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"
"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
go run ./cmd/memos --mode dev --port 8081
go test ./...
go test -run TestName ./path/...
go test -cover ./...
golangci-lint run
goimports -w .
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.http annotation
- 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
acl_config.go if 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.go interface
- Implement in
store/db/{driver}/*.go
- Add to
store/store.go if caching needed
- Add model in
store/{model}.go
Run Tests Against Multiple Databases
DRIVER=sqlite go test ./...
DRIVER=mysql DSN="user:pass@tcp(localhost:3306)/memos" go test ./...
DRIVER=postgres DSN="postgres://user:pass@localhost:5432/memos?sslmode=disable" go test ./...