欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

index

程序员文章站 2022-06-01 10:40:28
...

原文链接

链接

1. Effective GO

https://github.com/bingohuang/effective-go-zh-en

2. 格式化

在最开始学习GO的时候,写了几篇Blog,发现代码里面的对齐都是TAB,这让我很困惑,知道现在才知道,GO语言,默认使用TAB进行对齐。

当然GO还有自己的空格规则x<<8 + y<<16,向这份代码,我们根据空格就能知道计算的优先级了。

3. 注释

3.1. 包注释

Go语言要求package语句前加上注释,来介绍整个包,如果package包含多个文件,则只需要在其中一个文件中标注即可。

/*
Package regexp implements a simple library for regular expressions.

The syntax of the regular expressions accepted is:

    regexp:
        concatenation { '|' concatenation }
    concatenation:
        { closure }
    closure:
        term [ '*' | '+' | '?' ]
    term:
        '^'
        '$'
        '.'
        character
        '[' [ '^' ] character-ranges ']'
        '(' regexp ')'
*/
package regexp

需要注意的是,注释不是JavaDoc模式的,下面这种就不对了

/**
 *
 *  main
 *
 */
package main

3.2. 导出注释

在程序中,每个可导出(首字母大写)的名称都应该有文档注释。使用行注释的形式,行注释的第一行要以被导出的内容开头,并总结整个注释,如下,第一行以Compile开头

// Compile parses a regular expression and returns, if successful, a Regexp
// object that can be used to match against text.
func Compile(str string) (regexp *Regexp, err error) {

4. 命名

Go语言默认使用驼峰命名,请不要使用下划线

4.1. 包

包名用小写,不要带下划线,

不要使用import .的语句,很容易冲突

4.2. 字段Getter Setter

Getter方法不需要Get这个前缀,如下

obj.Owner()
obj.SetOwner(user)

4.3. 接口名

只包含一个方法的接口命名以er结尾。

5. 分号

在Go中,行末,不要加入分号。

分号其实是由词法分析器自动增加的。

6. 控制流

6.1. 变量重新声明

下面的这份代码,注意到其中的err申明了两次,上面这个err声明了两次,但是这并不是错误,编译器会帮忙解决这个问题,实际上err第二次只是被重新赋值而已。

package main

import (
    "fmt"
    "os"
)

func main() {
    f1, err := os.Open("file")
    fmt.Println(f1,err)

    f2, err := os.Open("file2")
    fmt.Println(f2,err)
}

当然这样的技巧只能在特殊情况才能生效

  • 本次声明与已声明的 v 处于同一作用域中(若 v 已在外层作用域中声明过,则此次声明会创建一个新的变量 §),
  • 在初始化中与其类型相应的值才能赋予 v,且
  • 在此次声明中至少另有一个变量是新声明的。

7. 函数

7.1. 可命名结果形参

在Go中,可以在函数上声明返回值变量,在返回的时候只需要一个return即可

package main

import (
    "fmt"
)

func f() (value int, info string) {
    value=1
    info="hello"
    return
}

func main() {
    fmt.Println(f())
}

7.2. Defer

defer是一种推迟执行的语法,被该关键词修饰的语句会在函数返回的时候执行

package main

import "fmt"

func f1(str string) {
    fmt.Println(str)
}

func main() {
    f1("hi1")
    defer f1("hi5")
    defer f1("hi4")
    defer f1("hi3")
    f1("hi2")
}
// 输出:
//hi1
//hi2
//hi3
//hi4
//hi5
//

8

9. 初始化

主要是init函数,一个文件可以有多个init函数,他们都会被调用,init函数在包的全局变量初始化以后执行

注意到下面这个代码,先输出abc, 与init的位置无关,init在全局变量之后执行

package main

import "fmt"

func p(str string) (int)  {
    fmt.Println(str)
    return 1;
}

var a = p("a")

func init() {
    p("init1")
}

var b = p("b")

func init() {
    p("init2")
}

var c = p("c")

func main() {
    p("main")
}
/*
输出:
a
b
c
init1
init2
 */
相关标签: default