一、 Go 编译快

  1. 依赖关系判断

第一点,所有导入的包必须在每个文件的开头显式声明,这样的话编译器就没有必要读取和分析整个源文件来判断包的依赖关系。

  1. 禁止环状依赖

第二点,禁止包的环状依赖,因为没有循环依赖,包的依赖关系形成一个有向无环图,每个包可以被独立编译,而且很可能是被并发编译。

  1. 记录依赖关系

第三点,编译后包的目标文件不仅仅记录包本身的导出信息,目标文件同时还记录了包的依赖关系。

二、 导入路径

  1. import 语句是导入的包路径,不是包名。

三、 包声明

  1. 每个 Go 语言源文件的开头都必须有包声明语句(即指明包名)

  2. 通常情况下,默认的包名就是包导入路径名的最后一段。

例外情况:

  1. main包的路径无关紧要
  2. 以 _test 结束的包名,即测试包,可与其它包在同一路径下共存
  3. 包含版本号的导入路径, 如 “gopkg.in/yaml.v2”。这种情况下包的名字并不包含版本号后缀,而是yaml。

四、 导入声明

  1. 有两种形式
    // 形式一
    import "fmt"
    import "os"

    //形式二
    import (
        "fmt"
        "os"
    )
  1. 通常将来自不同组织的包用空行分组
    import (
        "fmt"
        "html/template"
        "os"

        "golang.org/x/net/html"
        "golang.org/x/net/ipv4"
    )
  1. 导入包重命名
    import (
        "crypto/rand"
        mrand "math/rand" // alternative name mrand avoids conflict
    )

五、 包的匿名导入

  1. 导入包不使用包,会导致编译错误

  2. 用 _ 来重命名包,使包在编译时避免上述错误

  3. 在计算包级变量或者仅执行导入包的 init 函数时,使用匿名导入

    package main

    import (
        "fmt"
        "image"
        "image/jpeg"
        _ "image/png" // register PNG decoder
        "io"
        "os"
    )

    func main() {
        if err := toJPEG(os.Stdin, os.Stdout); err != nil {
            fmt.Fprintf(os.Stderr, "jpeg: %v\n", err)
            os.Exit(1)
        }
    }

    func toJPEG(in io.Reader, out io.Writer) error {
        img, kind, err := image.Decode(in)
        if err != nil {
            return err
        }
        fmt.Fprintln(os.Stderr, "Input format =", kind)
        return jpeg.Encode(out, img, &jpeg.Options{Quality: 95})
    }

六、 包和命名

  1. 避免包名使用可能被经常用于局部变量的名字,这样可能导致用户重命名导入包

七、 工具

  1. GOPATH

GOPATH 有三个子目录,src 目录用于保存源代码,pkg 目录保存编译后的包目标文件,bin 目录保存可执行程序。

  1. 下载包

go get xxx

  1. 构建包

go build 构建当前目录下的可执行程序 go install 构建可执行程序并安装到 GOPATH/bin 目录下 go build -i 命令将安装每个目标所依赖的包。

  1. 查询包

go list