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.
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.
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
Don't try to shorten variable names too much - e.g. prefer someAuthHandler to sAuthH
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
Always try to handle or at least log errors in-place where they occur instead of just passing (null, err) above to the caller.
Please try to split app in appropriate packages and try to keep classes one file if possible.
We use one root application config struct with any number of underlying sub-configs.
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.
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.
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
.
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
Service should serve OpenAPI spec - e.g. swagger.json so that anyone could check the version, state, etc.
Service should have health check endpoint. healthcheck list TBD
Handlers should only process input/output and delegate actual logic to the business layer. If needed - extract additional services for business logic.
3rd party libraries that we use:
- router - julienschmidt/httprouter https://github.com/julienschmidt/httprouter
- logger - logrus https://github.com/sirupsen/logrus
- config - viper https://github.com/spf13/viper
- cli - cobra https://github.com/spf13/cobra
- validator - validator.v9 https://github.com/go-playground/validator
- mongodb - mongo-go-driver https://github.com/mongodb/mongo-go-driver
- id/xid/uuid - https://blog.kowalczyk.info/article/JyRZ/generating-good-unique-ids-in-go.html
All integration tests should be cucumber based.
Note: Be sure to launch tests with -race flag to avoid race conditions.
For now we only will use go lint and elaborate on using anything else after Sonar updates.
Seed app will contain:
- gRPC
- Swagger
- Cucumber tests
- HTTP router
- Config with viper
- Validator for inputs
- Mongodb usage
- ???