Go 🐹

Hero image for Go 🐹

Linting

We mainly use the built in command go vet for automated code checks.

Formatting

  • Use tabs with 8 tab size for indentation.
  • Format the syntax using go fmt.
  • Use a single empty line to break between statements to organize logical chunks of code.
  • End each file with a newline.

Naming

  • Use UpperCamelCase for public and lowerCamelCase for private interfaces, structs, variables and functions.

    // Bad
    type hello_world interface{}
    
    type fizz_buzz struct{}
    
    var my_array []string
    my_array := []string{}
    
    func foo_bar() {
      // some code
    }
    
    // Good
    // public
    type HelloWorld interface{}
    
    type FizzBuzz struct{}
    
    // private
    var myArray []string
    myArray := []string{}
    
    func fooBar() {
      // some code
    }
    

Imports

  • Organize packages in group, separated by blank line between each group.

    import (
      // Standard library packages
    
      // Internal project packages
    
      // Third-party packages
    )
    
    // Bad
    import (
      "errors"
      "nimblehq/controllers"
      "net/http"
      "github.com/fizz/buzz"
      "nimblehq/models"
      "github.com/foo/bar"
    )
    
    // Good
    import (
      "errors"
      "net/http"
    
      "nimblehq/controllers"
      "nimblehq/models"
    
      "github.com/fizz/buzz"
      "github.com/foo/bar"
    )
    
  • Sort packages by alphabetical order for each group.

    // Bad
    import (
      "net/http"
      "errors"
    
      "nimblehq/models"
      "nimblehq/controllers"
    )
    
    // Good
    import (
      "errors"
      "net/http"
    
      "nimblehq/controllers"
      "nimblehq/models"
    )
    

Functions

  • Prefer declaring the type for each parameter over declare single type for all parameters.

    // Bad
    func fooBar(num1, num2 int, str1, str2 string) {
      // Some code
    }
    
    // Good
    func fooBar(num1 int, num2 int, str1 string, str2 string) {
      // Some code
    }
    
  • Prefer unnamed over named return parameters for return values.

    // Bad
    func fruit(name string) (color, taste string) {
      switch name {
      case "Banana", "Mango":
        color, taste = "Yellow", "Sweet"
      default:
        color, taste = "Unknown", "Unknown"
      }
      return
    }
    
    // Good
    func fruit(name string) (string, string) {
      var color string
      var taste string
    
      switch name {
      case "Banana", "Mango":
        color, taste = "Yellow", "Sweet"
      default:
        color, taste = "Unknown", "Unknown"
      }
      return color, taste
    }
    

Errors

  • DO NOT ignore errors using _ variables if the function returns an error. Check them to make sure the function is completed.

  • Prefer declare then check over inline error handling for error returning functions.

    // Bad
    if err := fooBar(); err != nil {
      // Error handling
    }
    
    // Good
    err := fooBar()
    if err != nil {
      // Error handling
    }
    

Testing

  • Any test file must have a _test.go suffix as the go test command automatically executes any file with names that match the file pattern *_test.go.

  • Any test function must have a Test prefix as the go test command automatically executes any function that match following pattern.

    func TestXxx(*testing.T) {
      // Testing code
    }