go 语言的包

Go 语言包的基本概念

Go语言 包的基本概念

Go语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方案。Go语言中为我们提供了很多内置包,如 fmt、os、io 等。

包时结构化代码的一种方式:每个程序都是由包(通常简称为pkg)的概念组成,可以使用自身的包或者从其他包中导入内容

如同其他一些编程语言中的类库或者命名空间的概念,每个Go文件有且仅属于一个包。一个包可以由许多以 .go为扩展名的源文件组成,因此文件名和包名一般来说都是不同的。

必须在源文件中非注释的第一行指明这个文件属于与哪个包 package pacakgeName 语句,通过该语句声明自己所在的包。package main 则表示一个可独立执行的程勋,每个Go应用程序都包含一个名为main的包。

一个应用程序可以包含不同的包,而且即使只使用main包,也不必包所有的代码都写在一个巨大的文件里:可以使用一些较小的文件,并且在每个文件非注释的第一行使用package main来指明这些文件文件都属于main包。如果打算编译报名不是main的源文件,如 pack1,编译后产生的对象文件将会是pack1.a而不是可执行程序。另外,要注意的是所有的包名都应该使用小写字母

标准库

标准库API:https://studygolang.com/pkgdoc

在Go的安装文件里包含了一些可以直接使用的包,即标准库。在Windows 下,标准库的位置在Go根目录下的子目录pkg\windoes_amd64中;在Linux下,标准库在Go根目录的子目录 pkg\linux_amd64中.

一般情况下,标准包会存放在$GOROOT/pkg/\$GOOS_GOARCH/目录下. GO的标准库包含了大量的包,(如:fmt 和os),但是也可以创建自己的包

如果想要构建一个程序,则包和包内的文件够必须以正确的顺序进行编译。包的依赖关系决定了器构建顺序。

属于同一个包的源文件必须全部一起被编译,一个包即是编译时的一个单元,因此根据惯例,每个目录都只包含一个包

如果对一个包进行更改或者重新编译,所有引用了这个包的客户端程序都必须全部重新编译

Go中的包模型采用了显示依赖关系的机制来达到快速编译的目录。编译器会从后缀名为.go的对象文件(需要且只需要这个文件)中提取传递依赖关系型的信息

如果A.go 依赖B.go,而B.go 又依赖C.go:

  • 编译C.go,B.go,然后是A.go
  • 为了编译A.go ,编译器读取的是B.go,而不是C.go

这种机制对于编译大型的项目时可以显著提升编译速度

示例

在目录example3 下,有目录cat 和main 。 在 cat 目录下有cat.go文件。 在main目录下有main.go文件

//cat.go 文件
package cat

import "fmt"

var Name string = "Tom"
var Age int = 5

//初始化函数
func init() {
	fmt.Println("this is cat package")
	fmt.Println("init 函数修改前", Name, Age)
	Name = "jack"
	Age = 3
	fmt.Println("init 函数修改后", Name, Age)
}
//main.go文件
package main

import (
	"dev_code/day9/example3/cat"
	"fmt"
)

//调用其他包,程序加载顺序   cat.go中全局变量-->cat.go中的init()函数--->main.go中的main()函数
func main() {
	fmt.Println("猫的名字:", cat.Name)
	fmt.Println("猫的年龄:", cat.Age)
}

//执行main.go文件 输出结果:
this is cat package
init 函数修改前 Tom 5
init 函数修改后 jack 3
猫的名字: jack
猫的年龄: 3

程序执行顺序

Go程序 的执行(程序启动)顺序如下:

  1. 按顺序导入所有被main包引用的其他包,然后在每个包中执行如下流程
  2. 如果该包又导入了其他包,则从第一部开始递归执行,但是每个包只会被导入一次
  3. 然后一相反的顺序在每个包中初始化常量和变量,如果该包含有init 函数的话,则调用该函数。
  4. 在完成这一切后,main也执行同样的过程。最后调用执行程序

在example5 目录下有demo包,main包,test包。 在demo包中有demo.go文件。在main包中有main.go文件。在test包中有test.go文件

//demo.go文件
package demo

import "fmt"

var Name string = "this is demo package "
var Age int = 20

func init() {
	fmt.Println("this is demo init()")
	fmt.Println("demo.package.Nam:", Name)
	fmt.Println("demo.package.Age:", Age)
	Name = "this is demo New"
	Age = 200
	fmt.Println("demo.package.Nam:", Name)
	fmt.Println("demo.package.Age:", Age)
}
//test.go文件
package test

import (
  // 在引用的包前面加上 _  表示只加载这个包,但是不进行引用包里的函数和变量
	_ "dev_code/day9/example4/demo"
	"fmt"
)

var Name string = "this is test package"
var Age int = 10

func init() {
	fmt.Println("this is test init()")
	fmt.Println("test.package.Nam:", Name)
	fmt.Println("test.package.Age:", Age)
	Name = "this is test New"
	Age = 100
	fmt.Println("test.package.Nam:", Name)
	fmt.Println("test.package.Age:", Age)
}
//main.go文件
package main

import (
	"dev_code/day9/example4/test"
	"fmt"
)

func main() {
	//main --->test--->demo
	fmt.Println("main.package", test.Name)
	fmt.Println("main.package", test.Age)
}


//执行main.go文件输出结果:
this is demo init()
demo.package.Nam: this is demo package 
demo.package.Age: 20
demo.package.Nam: this is demo New
demo.package.Age: 200
this is test init()
test.package.Nam: this is test package
test.package.Age: 10
test.package.Nam: this is test New
test.package.Age: 100
main.package this is test New
main.package 100

导入包时空白标识符的作用

如果导入了一个包,却没由使用它,则会在构建时引发错误,如imported andnot used

所以,我们可以使用空白标识符_ 来解决

方法一:

声明一个全局空白标识符(在main()函数之前),该标识符从 未使用的包中访问符号。

package main

import "os"

var _ = os.Open

func main() {
}

方法二:

在未使用的包前加上一个空白标识符。只初始化加载该包,而不去使用该包的函数和变量

package main

import _ "os"

func main() {
}

包的别名

在不同的父目录下,存在相同名字的包。比如,在example4和example5目录下,都有cat 包。那么,不管是导入,还是使用包里的函数或者变量,都很不方便,容易混淆。

此时我们可以在导入包的时候,在前面加上包的别名,在使用的使用,使用别名调用即可

package main
//导入fmt 包,同时,设置a 为fmt 包的别名
import a "fmt"

func main() {
  //在使用时,使用别名进行调用
	a.Println("通过包的别名进行调用")
}

//输出结果:
通过包的别名进行调用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值