手摸手学Go(02Go的包管理)|Go主题月

上期介绍了如下内容:

  • Go的前世今生
  • Go的特性
  • Windows环境变量配置

万物之始:Hello World

//文件名:helloworld.go
package main

import "fmt"

func main() {
	fmt.Println("HELLO, WORLD!")
}
复制代码

使用命令行操作.go文件

  • 运行Go文件

命令:go run helloworld.go

输出:HELLO, WORLD!

  • 编译成exe程序

命令:go build helloworld.go

会创建一个helloworld.exe文件,可以在命令行直接运行这个程序,输出同上。

Go的包概念

Go使用包(package)来组织代码。一个包由一个或多个Go文件组成,这个包存放在一个文件夹中,这个文件的名字描述了包的作用,一般来说包名和文件夹名相同。

每一个源文件的开始都会用package声明这个Go文件属于哪个包。
当我们看到fmt.println('Hello')这样的代码时,会想当然的认为源文件开头的import fmt中的fmt就是包名,但是事实并非如此。

import后面的最后一个元素是路径,也就是文件夹目录,并非包名

以Go提供的fmt包为例。

未命名文件.png

目录名和包名相同只是Go的一个惯例,并非永远如此。

import "fmt"
fmt.Println("xxx")
复制代码

这里虽然两行都是fmt,但含义不同,一个是路径,即$GOROOT/src.fmt这个路径。而第二行中的fmt则是包名。gc会在$GOROOT/src/fmt路径下找到fmt包的源文件。

可以给包起别名

import m "fmt" 

func main() {
    m.Pringln("Hello")
}
复制代码

使用一个容易辨识的单词作为别名,可以用这个别名来调用包中函数。

上面说过"fmt"是路径,那么用m作为别名,m是路径还是包名呢?

m其实是包名,因为下方可以使用m来调用函数

用点作为包的别名

import . "fmt"

func main() {
    Pringln("Hello")
}
复制代码

使用.作为包的别名后,调用该包中的函数不需要使用前缀

_导入包

import (
     "database/sql"
     _  "github.com/ziutek/mymysql/godrv"
 ) 
复制代码

按照网上的说法,使用_导包,会调用包中的init()函数,让导入的包做初始化,但是却不用包中其他的功能。这段话让人费解,既然不用为何要导入做初始化呢?要理解这个问题首先要了解Go的import原理。

  • 递归导包

当一个包被导入时,如果该包还导入了其它的包,那么会将其它的包先导进来,然后再对这些包中的包级常量和变量进行初始化,接着执行init()函数,以此类推。等所有被导入的包都加载完毕了,就会开始对main包中的包级常量和变量进行初始化,然后执行main包中的init()函数,最后执行main函数。

  • 多处引用,一次导入

程序的初始化和执行都起始于main包,如果main包还导入了其它包,那么就会在编译时将它们一次导入。有时一个包会被多个包同时导入,那么它只会被导入一次(比如很多包都会导入"fmt"包,但它只会被导入一次,因为没有必要导入多次)

  • 使用_导包的意义

第一,用_导如包,会执行该包中的init()函数,并初始化里面的变量。往往这些init()函数中是注册自己包里面的引擎(比如连接池注册等等)。这样导入一次后,别的包就不用再次初始这个包了,方便外部调用。

第二,Go的语法检查是非常严格的,如果导入一个包却不使用,编译时就会报错。使用_导包,不使用包中任何函数,是可以编译通过的。要注意的是用_导入的包是无法用它调用函数的

import _ "fmt"

//会报错
func main() {
    _.Pringln("Hello")
}
复制代码

Go和Java包含义的区别

  • 颗粒度不同

Java导包最小粒度是class

// 1.引用一个具体的类
import java.util.list;
// 2. 引用package下的所有类
import com.lark.demo.*
复制代码

Go导包最小粒度是package

//只能导入一个package,不能导入一个Struct(类)
import "fmt"
复制代码
  • package含义不同

Java的package只是class的目录,package本身不能定义方法和变量

Go的package是一组相关变量、方法、结构的集合。可以直接在package上定义变量和方法。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享