164 lines
3.4 KiB
Markdown
164 lines
3.4 KiB
Markdown
# Code Style
|
|
|
|
This document is only meant to teach you the code style used in this project and will not explain *why* this coding style is used.
|
|
|
|
* [Tabs vs Spaces](#tabs-vs-spaces)
|
|
* [Empty line between blocks and statements](#empty-line-between-blocks-and-statements)
|
|
* [Empty line between commented blocks](#empty-line-between-commented-blocks)
|
|
* [Variable names](#variable-names)
|
|
* [Types at the top](#types-at-the-top)
|
|
* [Private fields at the end of a struct](#private-fields-at-the-end-of-a-struct)
|
|
* [Package names](#package-names)
|
|
* [Use gofmt](#use-gofmt)
|
|
* [Code editor](#code-editor)
|
|
|
|
## Tabs vs Spaces
|
|
|
|
Use tabs for indentation and spaces for alignment:
|
|
|
|
```go
|
|
type AnimeTitle struct {
|
|
Romaji string
|
|
English string
|
|
Japanese string
|
|
Canonical string
|
|
Synonyms []string
|
|
}
|
|
```
|
|
|
|
## Empty line between blocks and statements
|
|
|
|
Bad:
|
|
|
|
```go
|
|
func() {
|
|
if true {
|
|
// Block 1
|
|
}
|
|
if true {
|
|
// Block 2
|
|
}
|
|
doSomething()
|
|
doSomething()
|
|
if true {
|
|
// Block 3
|
|
}
|
|
}
|
|
```
|
|
|
|
Good:
|
|
|
|
```go
|
|
func() {
|
|
if true {
|
|
// Block 1
|
|
}
|
|
|
|
if true {
|
|
// Block 2
|
|
}
|
|
|
|
doSomething()
|
|
doSomething()
|
|
|
|
if true {
|
|
// Block 3
|
|
}
|
|
}
|
|
```
|
|
|
|
## Empty line between commented blocks
|
|
|
|
A commented block is a sequence of lines preceded by a descriptive comment. Commented blocks should be treated as normal blocks and therefore require newlines separating them from other blocks.
|
|
|
|
Bad:
|
|
|
|
```go
|
|
func(a int, b int) int {
|
|
// Add one to a and b
|
|
a++
|
|
b++
|
|
// Calculate c as the sum of a and b
|
|
c = a + b
|
|
// Return c squared
|
|
return c * c
|
|
}
|
|
```
|
|
|
|
Good:
|
|
|
|
```go
|
|
func(a int, b int) int {
|
|
// Add one to a and b
|
|
a++
|
|
b++
|
|
|
|
// Calculate c as the sum of a and b
|
|
c = a + b
|
|
|
|
// Return c squared
|
|
return c * c
|
|
}
|
|
```
|
|
|
|
## Variable names
|
|
|
|
Variables are written in `camelCase` and should clearly state what they contain, preferably with no abbreviations. Common short names like `id` and `url` are allowed.
|
|
|
|
Iterator variables in loops are an exception to this rule and can be 1-letter, non-significant variable names, usually `i` and `j`. `index` is also quite common.
|
|
|
|
## Early returns
|
|
|
|
Do not wrap a whole function in 1 if-block to check parameters. Use early returns.
|
|
|
|
Bad:
|
|
|
|
```go
|
|
func DoSomething(a string, b string) {
|
|
if a != "" && b != "" {
|
|
doIt(a, b)
|
|
}
|
|
}
|
|
```
|
|
|
|
Good:
|
|
|
|
```go
|
|
func DoSomething(a string, b string) {
|
|
if a == "" || b == "" {
|
|
return
|
|
}
|
|
|
|
doIt(a, b)
|
|
}
|
|
```
|
|
|
|
## Types at the top
|
|
|
|
`type` definitions should be placed at the very top of your files. Variables, constants, interface implementation assertions and the `package` statement are the only constructs allowed above `type` definitions.
|
|
|
|
## Private fields at the end of a struct
|
|
|
|
This is not an absolute rule but try to keep private fields at the end of a struct.
|
|
|
|
```go
|
|
type MyType struct {
|
|
PublicA string
|
|
PublicB string
|
|
PublicC string
|
|
|
|
privateA int
|
|
}
|
|
```
|
|
|
|
## Package names
|
|
|
|
Package names should be short lowercase identifiers and tests should be written using the black box pattern. Black box testing can be enabled by adding the suffix `_test` to the package names in `*_test.go` files. It will enable you to test your library like it would be used by another developer, without internal access to private variables.
|
|
|
|
## Use gofmt
|
|
|
|
Your IDE should automatically call `gofmt` to format your code every time you save the file.
|
|
|
|
## Code editor
|
|
|
|
It is highly recommended to use [Visual Studio Code](https://code.visualstudio.com/) as it has an excellent Go plugin and the repository includes workspace settings to get you started quickly. |