Skip to content

Instantly share code, notes, and snippets.

@igogrek
Last active April 27, 2024 03:59
Show Gist options
  • Save igogrek/4df77b3a1adb508e7a12fd14d2f7e955 to your computer and use it in GitHub Desktop.
Save igogrek/4df77b3a1adb508e7a12fd14d2f7e955 to your computer and use it in GitHub Desktop.
Our team Go code custom conventions

General conventions

Effective go

Our main source of code conventions is the standard GO conventions from effective go - see https://golang.org/doc/effective_go.html

Please try to follow them as much as possible.

Context

All of our apps should have a context. This means one struct with references to the underlying dependencies. No global variables should exist. Context should be manually initialized at the start of the service with cascading initialization of all the underlying dependencies hierarchically. Constructors should be used to pass the dependencies.

This approach is used in absence of a nice dependency injection mechanism, but it has it's own benefits too.

Variable declaration with assignment

Always prefer using := to declare variables with assignment instead of using var keyword.

Only use var if there's no initial/default value for the variable and you don't want to set one for a reason.

var someStuff int     // GOOD (only if no value)
...
someStuff = 1
var someStuff int = 1 // BAD
otherStuff := 2       // GOOD if initialized

Variable names

Don't try to shorten variable names too much - e.g. prefer someAuthHandler to sAuthH

Todo format

Our todo format is // TODO - don't use other styles and only use todos for WIP pull requests.

If you need to leave to TODO - be sure to create a ticket for that and mark TODO with this ticket - e.g. // TODO fix this JIRA-123

Error handling

Always try to handle or at least log errors in-place where they occur instead of just passing (null, err) above to the caller.

Packages

Please try to split app in appropriate packages and try to keep classes one file if possible.

Config

We use one root application config struct with any number of underlying sub-configs.

Entry point

If there's only one entry point - main.go should be located in the app root.

For multiple entry points - there should be a cmd folder.

Utils

Don't overuse util packages - try to extract common functions to other packages and really use utils just for actual common utils.

Try to never even create a util package, its purpose is not very clear and hence not intuitive.

"Other" files

Store "other" files in contrib folder - this goes for swagger, makefiles, and config.example (do not commit config.yaml)

Makefile should be in the root of the project only if it's the default way to build the project (usually it's go build ).

Also other files like documentations should be put inside their own context related directory, like doc.

Services

gRPC

All of our services will communicate with each other through gRPC. Common models should be extracted to common repo with just proto definitions.

See example here: https://tlbcg-wbench.wesp.telekom.net/gitlab/r2b/r2b-msa-common

Swagger

Service should serve OpenAPI spec - e.g. swagger.json so that anyone could check the version, state, etc.

Healthchecks

Service should have health check endpoint. healthcheck list TBD

No business logic in handlers

Handlers should only process input/output and delegate actual logic to the business layer. If needed - extract additional services for business logic.

Libraries

3rd party libraries that we use:

Tests

Integration tests

All integration tests should be cucumber based.

Note: Be sure to launch tests with -race flag to avoid race conditions.

Tools

Linter

For now we only will use go lint and elaborate on using anything else after Sonar updates.

Seed

Seed app will be available TBD

Seed app will contain:

  • gRPC
  • Swagger
  • Cucumber tests
  • HTTP router
  • Config with viper
  • Validator for inputs
  • Mongodb usage
  • ???
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment