Go 的源代码是按 package 方式组织,再通过 import 引入使用。在理解 improt 前有必要来罗嗦下 Go 的代码组织结构 和理解 package。

工作目录

在 Go 中代码保持在称之为 workspace 的系统文件夹中。这个工作目录下有三个根目录:

  • bin 包含可执行文件 。
  • pkg 包含不同操作系统架构的包二进制文件。相当于编译后的库文件。
  • src 包含按包方式组织的源代码。

其中 bin 和 pkg 文件夹是在调用 go 命令安装和编译源代码时自动生成。而 src 下可组织多个包,且能使用版本控制工具。

注意,必须让 Go 知道工作目录的位置,这样才能知道包的具体位置。通过设置环境变量 GOPATH 来指定。

export GOPATH=/home/dev/gowork/ 

导入包

improt 便是用一个独一无二的字符串路径来指向包,而包的导入路径是基于工作目录或者的。因为 Go 会在 工作目录 src 子目录下查找包。

标准包使用的是给定的短路径,如“fmt”、“net/http”,但你自己的包,需要在工作目录下指定一个目录,同时预防和以后的代码包路径发生冲突。以便我们作为个人开发者,基于 github 的话,那么我们可以建立自己的代码基目录,github.com/user

improt 则导入包,既然是包地址,实际上就是基于工作目录的文件夹目录。如:

先创建代码库: $GOPATH/src/ysqi/lib/lib.go

package lib

import "fmt"

func SayHello() {
	fmt.Println("Hello,YSQ :) ")
}

再新建一个App:$GOPATH/src/ysqi/app/main.go

package main

import "ysqi/lib"

func main() {
	lib.SayHello()
}

如上,使用import "ysqi/lib" 导入包,从而调用 SysHello 方法 。再看看 这个代码lib.SyaHello中的lib标识的含义。他标示调用包lib,而对比 import “ysqi/lib” 中的 lib,此 lib 是包路径的一部分,并不代表包名。

也就是说 ysqi/liblib.SyyHello() 里的lib含义不同。包名和包路径不需要完全一致,如:

# file Path: $GOPATH/src/ysqi/mylib/lib.go

package lib

import "fmt"

func SayHello() {
	fmt.Println("Hello,I'm in myLib :) ")
}

调用 lib 的方式变成了import "ysqi/mylib"

package main

import "ysqi/mylib"

func main() {
	lib.SayHello()
}

那么 一个目录下可以有多个包吗? 这是不可以的,Go 编译失败,错误信息:

can't load package: package .: found packages lib (lib.go) and mylib (mylib.go) in ...

导入包的多种方式

实际上,导入使用包有三种方式,不同方式用途不一样:

  • import “ysqi/lib”

常规方式,通过包名lib调用SayHello方法。lib.SayHello()

  • import m “ysqi/lib”

这里的 m 是包名 lib 的别名,m.SyayHello() 。该方式合适的场景:

1.包名过于复杂或者意思不明确。

如使用 mywebapp/libs/mongodb/db 包时,不确定此 db 是哪种类型,故可以使用别名来明确含义:

import mongo "mywebapp/libs/mongodb/db"

2.包名和其他包冲突。

世界之大,变化无穷。现在我们有库 db ,但没过几年出现了另一种DB,叫云DB。但包名是一样的,分别用别名区分:

import mongo "mywebapp/libs/mongodb/db"
import ydbgo "mywebapp/libs/yundb/db"
  • import . “ysqi/lib”

这里的点.符号表示,对包 lib 的调用直接省略包名,你我以后就是一家人,不分彼此,你的东西就像我就的一样,随便用。

package main

import . "ysqi/lib"

func main() {
	SayHello()
}
  • improt _ “ysqi/lib”

这里说的是我还不准备现在使用你们家的东西,但得提前告诉一声。你先做好准备,先准备好饭菜,等我来就行,也有可能我压根就不来。

package main

import _ "ysqi/lib"

func main() {
	 
}

特殊符号“_” 仅仅会导致 lib 执行初始化工作,如初始化全局变量,调用 init 函数。

总结

import 导入 Go 包有几种方式,用途不同。 代码统一存储在工作目录下,工作目录里边有会很多个包,不同包按目录组织,包下面由多个代码文件组成。导入包时按包的唯一路径进行导入,导入的包默认是必须要使用,如果不使用则编译失败,需要移除,减少不必要代码的引入,当然还有其他使用场景。默认情况下,我们使用文件名做为包名,方便理解。不同包组织不同的功能实现,方便理解。