Golang development habits: variable, constant declaration & usage conventions

insert image description here

Learn and record some of the content of the second and third chapters of "Go Language Improvement Road".

1. Basic principles

In the development of Golang, the simple and consistent naming principle can be followed, and the naming should be concise, easy to understand and consistent.

  • package declarations
    Golang's package declarations are named as single words in lowercase:
shopservice、utils、logs、tcc、logconfigs、encoding    [good]

It is not recommended to name in the form of compound words:

shop_service、log_configs    [bad]
  • Variable declarations
    do not repeat type information when it already exists:
users []*User    [good]
userList []*User     [bad]

Use camelCase to declare variables, not underscores:

var userInfo *User    [good]
var user_info *User    [bad]
  • Constant declarations
    use camelCase to declare variables, not underscores:
const (
    TaskTypeA = "A"    [good]
    Task_Type_B = "B"    [bad]
)

For proper nouns or certain constants, use all caps:

const (
    SIGABRT = Singnal(0x6)    [good]
    SIGALRM = Singnal(0xe)    [good]
    sig_abrt = Singnal(0x6)    [bad]
)
  • Interface declarations
    Prefer single-word names for interface types. For an interface with a unique method (method) or a combination of multiple interfaces with a unique method, the Go language convention is to name it with "method name + er".
type Writer interface {
    
        [good]
}

type Write interface {
    
        [bad]
}
  • For loop logo declaration
    Where there is a context description, try to be as simple and clear as possible, avoid naming a large section of known meanings, and avoid redundancy:
for i := 0, i < len(s); i++ {
    
        [good]
    v := s[i]
    ...
}

for index := 0, index < len(s); index++ {
    
        [bad]
    value := s[index]
    ...
}

2. Variable declaration

2.1. Package level variables

  • Package-level variable declaration Package-
    level variables can only use the variable declaration form with the var keyword, and it is recommended to place variables with similar meanings and functions in a var block when declaring, and the type is recommended to be moved later:
var (    [good]
    a = int32(1)
    f = float32(3.14)
)

var (    [bad]
    a int32 = 1
    f float32 = 3.14
)
  • Delayed declaration
    For package-level variables that are not initialized immediately when declared, you can declare them directly:
var a int32
var f float32
  • Use the principle of proximity
    Not all package-level variables must be placed in the file header, and can be placed above the function used for the first time:
var ErrNoUserInfo = errors.New("用户信息不存在")

func GetUserInfo(name string) (*User, error) {
    
    
    ...
    return nil, ErrNoUserInfo
}

2.2. Function level variables

  • Function-level variable declaration
    Usually, for lazily initialized local variables, var can be used for forward declaration:
func GetUserInfo(name string)(*User, error) {
    
    
    // 前置声明
    var user *User
    if user, err := getUserDB(name); err != nil {
    
    
        return nil, err
    }
    return user, nil
}
  • For declared and initialized local variables, use the short form declaration:
[good]
taskType := int32(1)
s := []byte("hlelo")

[bad]
var taskType int32 = 1
var s []byte = []byte("hello")
  • For branch control variables or variables in for loops, use short declarations:
[good]
func Do(userName string) (*User, error){
    
    
    var u User
    if u, ok := userMap[userName]; !ok {
    
    
        return nil, ErrNoUser
    }
   for _, s := range u.Shops {
    
    
       handleShop(s)
       ...
   }
}

[bad]
func Do(userName string) (*User, error){
    
    
    var user User
    if user, existUser := userMap[userName]; !existUser {
    
    
        return nil, ErrNoUser
    }
   for _, userShop := range user.Shops {
    
    
       handleShop(userShop)
       ...
   }
}

3. Constant declaration

  • Constant declarations are similar to package-level variable declarations. Constants of the same type can be aggregated in a const block. The default type is not specified (such as a is of type int), and special types are specified later (f is of type float64).
const (    [good]
    a = 1
    f = float64(3.14)
)

const (    [bad]
    a int32 = 1
    f float64 = 3.14
)
  • For constants with incremental declarations, iota syntax sugar can be used to simplify, avoiding handwritten redundant incremental values
[good]
const (
    _ = iota // 0
    A
    B
    C
)

[bad]
const (
    A = 1
    B = 2
    C = 3
)

4. Zero value is available

  • slice append zero value available
var list []int // 该切片声明为零值
list = append(list, 1) // 依然生效,会自动初始化list
  • mutex zero value available
var mu sync.Mutex // 该mutex声明为零值
mu.Lock()
mu.Unlock()
  • struct zero value is available
type Person struct {
    
    
   Name string
   Age int
   Child *Person
}

func main() {
    
    
   var p Person // 声明结构体后,自动为其内部各字段赋零值
   p.Age = 1
   p.Name = "test"
   p.Child = &Person{
    
    }
}
  • Zero-valued pointer call method available
func (p *Person) GetPersonName() string {
    
    
   if p == nil {
    
    
      return "<nil>"
   }
   return p.Name
}

func main() {
    
    
   var p *Person             // 声明零值指针
   name := p.GetPersonName() // 零值指针调用方法
   fmt.Println(name)         // 输出<nil>,表明零值指针调用方法可行
}

Guess you like

Origin blog.csdn.net/pbrlovejava/article/details/128171116