在刚学Go的时候,尤其是之前有学过Java的时候,会对Go的导包感觉优点奇怪
首先要明确的是,Go导入的是文件夹(文件夹下的package),Java导入的是具体的文件
当然了关于Java上的别名,静态导入,匿名类加载在Go上都有这些都有,知识语法不同,概念上也没啥区别
// Go的导包 import ( "fmt" "github.com/opesun/goquery" ) //Java的导包 import org.dom4j.DocumentException;
比如经常导入的fmt来分析
GO编译器依次会去GOROOT/src,GOPATH1/src,GOPATH2/src ... 下去寻找名为fmt的文件夹
下面有许多的go文件,所有的以大写开头的变量,函数,结构等等的都会被导出
fmt.Println()
的Println其实是print.go里的一个方法
那么疑问又来了,每个Go文件的第一行都会写package xxx,那么这又是做什么用的呢
其实严格意义上说Go语言导入的包后,是通过package name来使用
fmt文件夹下的所有go文件的第一行都是 package fmt
,包名与文件夹名是相同的,所以体现不出来,当然包名和文件夹名相同是一种规范的做法
比如这么一个文件tmaize.net/demo/haha/Print.go,我们的包名设为common
package common import "fmt" func P(msg string){ fmt.Println(msg) }
那么使用的时候
import "tmaize.net/demo/haha" haha.P("Hello World") //报错 common.P("Hello World") //这才是对的
所以:这就很好理解为什么一个文件夹下所有的go文件(一级目录)的package name只能取同一个名字了
为什么这么设计我个人理解应该是划分模块避免单个文件过大,抑或是容易针对单个文件做测试案例?
通过下面是Java和Go的dmeo应该比较容易看出来
Go common/func1.go package Common func Func1(){} common/func2.go package Common func Func2(){} Java Common.java public class Common { // 两个语言的命名规范真的是.... public static void Func1() {} public static void Func2() {} }
最后要注意的是最好不要使用local import
如果使用了,那么针对项目 go build tmaize.net/demo
会报错的 local import "./haha" in non-local package
local import的主要用途是写简单的小脚本非项目,直接对文件进行go run,go build是没问题的
在看完包的时候,大致就应该明白了Go的依赖管理方式
当我们的项目需要依赖自己(不要使用相对路径)/别人项目时候,通过import很容易就能把别人的轮子导进来使用
GO编译器依次会去GOROOT/src,GOPATH1/src,GOPATH2/src ... 下去我们import的路径
但是肯定会有这种情况,我们要用到A项目,但是A项目又依赖B项目,但是A项目在GOPATH是存在的,但是B项目我们没有,难道要自己找到B项目,然后手动放到GOPATH的src下吗?
这时候就应该有一个依赖管理工具了,比如Java的Maven和Gradle
对应的Java的依赖管理工具就是go get,使用go get A项目的时候会自动分析A项目的依赖,然后吧他们都下载到GOPATH的第一个路径中
但是问题又来了,go get实际就是get clone,下载的都是最新的,没办法指定版本,而且我们的两个项目依赖同一个第三方库的不同版本,依赖脱离于项目等等这些都是问题
为此,go在后来的版本中加入了vendor。就是优先从项目源码树根目录下的vendor目录查找代码,这样就吧依赖和项目合到一起了,类似于NodeJs的node_modules目录,但是指定版本来事没办法实现,只能手动到vendor目录下切换依赖版本
所以又有了godep,glide,govendor等工具
项目构建全靠GOPATH,因此就要将这个项目添加到GOPATH
GOPATH可以配置多个的,windows下使用;隔开,第一个GOPATH是用来go get安装全局的依赖之类的
项目下会有三个目录,分别是src,bin,pkg
任意目录下 go build 比如go install tmaize.net/demo 会在src的同级创建pkg目录,产生平台相关的归档文件
注意:也可以针对某个文件使用go build,会直接产出可执行文件
go install 其实是go build多了一步骤,如果程序有main包会在bin目录下生成可执行文件 项目名.exe