Code style of goland code specification

The only measure of code quality is the number of times you swear while reading it

An excellent team should maintain a consistent coding style. In practice, we have found that if the coding style of a project is inconsistent, it will cause the project to be messy, not conducive to cross-module development, affect development efficiency, and make people want to curse.

Before defining our coding style, I first recommend a very good book "clean code". If you have time, you can read it and sharpen your knife without losing time.

Naming basic rules

  • From the caller's perspective, the package is not for your own use.
  • Simple and clear
  • Use common, well-known abbreviations. For example instead bufofbufio
  • If the abbreviated name creates ambiguity, discard or change it

Package names

  • The package name is consistent with the directory name
  • In most cases using named imports, renaming is not required

​ Use the caller less often to create aliases, unless the name is too bad

  • Package names should be all lowercase, no underscores, no capital letters
  • Singular, no plural

Example:

Bad:

configs
third_party
thirdParty
...

Import package

(1) If the package name does not match the last element of the import path, an import alias must be used

import (
    client "example.com/client-go"
    trace "example.com/trace/v2"
)

It is recommended to use aliases if the last element of the path is a version number to avoid ambiguity.

(2) In all other cases, avoid importing aliases unless there is a direct conflict between the imports

import (
    "net/http/pprof"
    gpprof "github.com/google/pprof"
)

(3) If there are duplicate names, please keep the standard package naming, customize the alias or third-party package

(4) It is prohibited to use relative paths to import. All import paths must comply with go get standards.

file name

  • File names should be kept simple and easy to understand.
  • File names should be all lowercase, no uppercase letters should appear, and different words should be separated by underscores.
  • File names should avoid plural forms

Example:

Bad:

configs.yaml
cloudServer.go
cloud-server.go

function name/method name

  • Function names/method names should remain in verb/verb-object form
  • Abbreviations should not be used unless they are recognized abbreviations
  • Avoid names that are too long. Long names do not make them more readable. A useful documentation or comment is usually more valuable than an extra long name.

Example:

Bad:

container.createContainer(in)

Good:

container.create(in)
  • Go does not provide automatic support for getters and setters. For a certain variable or field, the getter name does not need to be carried Get, and the setter name Setstarts with

note : If you have a field named owner (lower case, not exported), its getter should be named Owner (upper case, exportable) instead of GetOwner.

Example:

Good:

func Owner() string {
    
    
    ...
}


func SetOwner(ower string) string {
    
    
    ...
}

Bad:

func GetOwner() string {
    
    
    ...
}
  • Use English for naming to avoid word mistakes.

Example:

Bad

func (u *userRepo) syncDepartmentFormDatabase() {
    
    
    ...
}

From rather than Form.

Interface name

  • By convention, an interface containing only one method should be named after the name of the method plus the -er suffix, such as Reader, Writer, Formatter/CloseNotifier, etc.
type Reader interface {
    
    
	  Read(p []byte) (n int, err error)
}
  • Nouns are used for interface names and verbs are used for interface method names.
  • A single verb should be used unless the included method name is not directly related to the interface name.
type ContainerRepo interface {
    
    
    Create() error
    Delete() error
    ...
}

Structure name

  • Struct names must be named strictly in noun form.
  • Avoid using plurals
  • Use camelCase for multiple words

Example:

Good:

type Container struct {
    
    }


type ContainerInfo struct {
    
    }

Bad:

type ContainerDelete struct {
    
    }


type Containers struct {
    
    }


type Containerinfo struct {
    
    }

constant name

  • If it is a constant of enumeration type, you need to create the corresponding type first
type Scheme string


const (
    Http  Scheme = "http"
    Https Scheme = "https"
)
  • If the function of the module is more complex and the constant names are easily confused, in order to better distinguish the enumeration types, you can use the complete prefix
type Symbol string


const (
    SymbolAdd Symbol = "+"
    SymbolSub Symbol = "-"
)

variable name

  • If it is a global variable, be sure to use the full name and be sure to add comments
// configPath is the absolute path of config file from the command line.
var configPath string
  • If it is a local variable, in a relatively simple environment (a small number of objects and a strong focus), some names can be abbreviated from complete words to single letters.
user 可以简写为 u
userId 可以简写 uid
  • If the variable type is bool, the name should start with Has, Is, Can or Allow
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool

Error

  • ErrorType names Errorend with
type CodeError struct {
    
    
    message string
}
  • ErrorVariables of type, Errstarting with
var ErrTokenExpired = errors.New("token expired")
  • Variables of return type Errorare abbreviated usingerr
func test() {
    
    
    res, err := container.create(in)
    ...
}
  • Do not use the same err to receive different types of errors.

Example:

Good:

func (c *container)Update(ctx context.Context,name string) error {
    
    
    res, listErr := c.list()
    if listErr!=nil {
    
    
        return listErr    
    }


    updateErr := c.update(name)
    if updateErr!=nil {
    
    
        return updateErr    
    }
    ...
}

Bad:

func (c *container)Update(ctx context.Context,name string) error {
    
    
    res, err := c.list()
    if err!=nil {
    
    
        return err    
    }


    _, err = c.update(name)
    if err!=nil {
    
    
        return err    
    }
    ...
}

URL

  • URL names are all lowercase
  • Use forward slashes /to indicate hierarchical relationships
  • Use hyphens -to improve readability of names in long paths and do not use underscores in URLs_
  • The URL should not contain a forward slash at the end/
  • File extension should not be included in URL
  • The URL must be clearly identifiable by name, but the server architecture must not be exposed

Bad:

/GetUserInfo
/photos_path
/My-Folder/my-doc/
/user/user-list

Good:

/user/list
/user/operator-logs

Proto

  • The RPC of service should refer to the style of function name/method name.
  • In the proto file, the naming style of the structure (message of proto) is as follows:
message CreateSecurityGroupRequest {}


message CreateSecurityResponse {}


// 除了request和response外,其他的命名风格需保持名词形式
message SecurityGroupInfo{}


enum Policy{}

other

  • The name of the package content cannot start with the package name because there is no need to repeat the package name.

For example: httpThe HTTP service provided by the standard package is named http.Serverinstead HTTPServer. User code http.Serverrefers to the type via , so there is no ambiguity.

package http


type Server struct {
    
    }
  • Type names in different packages can be the same because the client can distinguish them by the package name

For example: The standard library contains multiple types named Reader, including jpeg.Reader, bufio.Readerand csv.Reader. Every package name paired with Reader is a good type name.

package jpeg


type Reader struct {
    
    }
package bufio


type Reader struct {
    
    }

format

We don't have much choice, because Go has been standardized, and there is no such war in the Go world.

Json/Bson

  • It should be pointed out in particular that we often need this field when defining a structure id. In order to be concise and easy to understand without ambiguity, we stipulate that in a structure, all fields involved idmust be prefixed to distinguish them.
  • All json/bson fields with multiple words use underline format and do not use camel case format.
type SecurityGroup struct {
    
    
    SgID string `json:"sg_id"`
    Rule Rule `json:"rule"`
    ...
}
type Rule struct {
    
    
    RuleID string `json:"rule_id"`
    ...
}

blank line style

  • After the logic of a piece of code is processed, there should be an empty line
  • There should be a blank line after if err

Example:

Good:

func Create() error {
    
    
    if err:=container.create();err!=nil {
    
    
        return err    
    }


    if err:=store.update();err!=nil {
    
    
        return err    
    }
    ...
}
func check() error {
    
    
    isExist, err := contaier.check()
    if err!=nil {
    
    
        return err
    }
    if isExist {
    
    
        ...
    }


    if err:=store.update();err!=nil {
    
    
        return err    
    }
    ...
}
  • The first line of code in the function is not a blank line

Example:

Bad:

func test() error {
    
    
    
    if err:=container.create();err!=nil {
    
    
        return err
    }
    ...
}
  • It is recommended that the line before the return statement on the last line in the function be a blank line.
func test() error {
    
    
    fmt.Println("test")


    return nil
}

import style

  • Follow our custom import order: standard package, third-party package, and project package, separated by blank lines.
import (
	"flag"
	"os"

	"github.com/go-kratos/kratos/v2"
	"github.com/go-kratos/kratos/v2/config"
	"github.com/go-kratos/kratos/v2/config/file"
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/go-kratos/kratos/v2/transport/http"

	"backend/internal/conf"
	"backend/internal/data"
)

Guess you like

Origin blog.csdn.net/qq_26356861/article/details/131289555