Golang语言基于GOPATH方式管理包(package)

                                              作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

一.包概述

1 为什么要使用包

使用包的原因主要有两个:
	- 1.我们不能把所有的函数都放在同一个源文件中,可以分门别类的把函数放在不同的源文件中;
	- 2.解决同名问题: 两个人想要定义一个同名的函数,在同一个文件中是不可以定义相同名字的函数,此时可以用包来区分;

Go语言中支持模块化的开发理念,在Go语言中使用包(package)来支持代码模块化和代码复用。

一个包是由一个或多个Go源码文件(.go结尾的文件)组成,是一种高级的代码复用方案,Go语言为我们提供了很多内置包,如fmt、os、io等。

2 包定义

我们可以根据自己的需要创建自定义包。一个包可以简单理解为一个存放"*.go"文件的文件夹。

该文件夹下面的所有"*.go"文件都要在非注释的第一行添加"package packagename"声明,声明该文件归属的包。
	- package:
		声明包的关键字。
		
	- packagename:
		包名,可以不与文件夹的名称一致,不能包含"-"符号,最好与其实现的功能相对应。
		
温馨提示:
	- 1.一个文件夹下面直接包含的文件只能归属一个包,同一个包的文件不能在多个文件夹下。
	- 2.包名为main的包是应用程序的入口包,这种包编译后会得到一个可执行文件,而编译不包含main包的源代码则不会得到可执行文件。

3 包的引入格式

要在当前包中使用另外一个包的内容就需要使用import关键字引入这个包,并且import语句通常放在文件的开头,package声明语句的下方。

完整的引入声明语句格式如下:
	import importname "path/to/package"
	
  其中:
    - import:
      引入包的关键字。

    - importname:
      引入的包名,通常都省略。默认值为引入包的包名。

    - path/to/package:
      引入包的路径名称,必须使用双引号包裹起来。
  
  
一个Go源码文件中可以同时引入多个包: 
	- 语法一:(一个Go源码文件中可以同时引入多个包)
import "fmt"
import "net/http"
import "os"


	- 语法二:(当然可以使用批量引入的方式)
import (
	"fmt"
	"net/http"
	"os"
)

4 包的别名

引入的多个包中存在相同的包名或者想自行为某个引入的包设置一个新包名时,都需要通过importname指定一个在当前文件中使用的新包名。例如,在引入fmt包时为其指定一个新包名f。

	- 导入时:
import f "fmt"

	- 使用时:
f.Println("Hello world!")

5 匿名引入

如果引入一个包的时候为其设置了一个特殊"_"作为包名,那么这个包的引入方式就称为匿名引入。

一个包被匿名引入的目的主要是为了加载这个包,从而使得这个包中的资源得以初始化。 

被匿名引入的包中的init函数将被执行并且仅执行一遍。举个例子:
	import _ "github.com/go-sql-driver/mysql"

匿名引入的包与其他方式导入的包一样都会被编译到可执行文件中。

需要注意的是,Go语言中不允许引入包却不在代码中使用这个包的内容,如果引入了未使用的包则会触发编译错误。

二.自定义包快速入门案例

1 包的环境准备

1.1 包的组织结构及环境声明

如上图所示,我的代码组织结构如上图所示。


本案例我定义的GOPATH环境变量为"GOPATH='/Users/yinzhengjie/golang/gosubjects'"

1.2 配置GO111MODULE

此处我想要使用GOPATH的方式导入包,则需要临时设置GO111MODULE的值为auto或者off
			go env -w GO111MODULE=auto

要启用go module支持首先要设置环境变量GO111MODULE,通过它可以开启或关闭模块支持,它有三个可选值:off、on、auto。
        GO111MODULE=off:
		        禁用模块支持,编译时会从GOPATH和vendor文件夹中查找包。
        GO111MODULE=on:
				启用模块支持,编译时会忽略GOPATH和vendor文件夹,只根据 go.mod下载依赖。
        GO111MODULE=auto:
				当项目在$GOPATH/src外且项目根目录有go.mod文件时,开启模块支持。

2 db文件夹代码

2.1 haha.go代码

// 注意,包名称可以和文件夹不同名称哟~
package dbutils

import "fmt"


// 首字母大写,外部的包可以访问该函数
func Haha(){
	fmt.Println("in db package .... Haha")
}

// 首字母小写,外部的包不可以访问该函数,但内部同一个包是可以相互访问的。
func hehe(){
	fmt.Println("in db package .... hehe")
}

2.2 xixi.go代码

// 注意,包名称可以和文件夹不同名称哟~
package dbutils

import "fmt"

// 标识符首字母大写,可以被其他包访问
func GetConn() {
	fmt.Println("in db package .... getConn")
}

func Xixi(){
	fmt.Println("in db package .... Xixi start")

	// 同一个包的函数是可以相互访问的,尽管首字母是小写的
	hehe()

	fmt.Println("in db package .... Xixi end")
}

3 utils文件夹代码

3.1 haha.go代码

package utils

import (
	"fmt"
)
 
func Haha(){
	fmt.Println("in utils package .... Haha ")
}

3.2 xixi.go代码

package utils

import "fmt"

func Add(){
	fmt.Println("in utils package .... Add")
}

func Xixi(){
	fmt.Println("in utils package .... Xixi")
}

4 main包代码

/*
1.package用于进行包的声明,推荐包的声明和这个包所在的文件夹同名;
2.main包是程序的入口包,一般main函数会放在这个包下;
*/
package main

/*
	1.导包的包名是从"$GOPATH/src/"后开始计算的,使用"/"进行路径分隔;
	2.导包路径不推荐使用中文;
	3.如果有多个包建议一次性导入,当然你也可以使用"import"关键字逐行导入每个包;
*/
import (
	"fmt"
	// 此处导入的包是包所在的文件夹,但是使用包的时候不是db,而是dbutils哟~
	"gocode/devops/05-package/01-oa/db"
	// 此处我们也可以给包起别名,一旦起别名,则原来名为utils则不可以使用了,而是使用别名调用。
	yinzhengjie "gocode/devops/05-package/01-oa/utils"
)

func main() {
	fmt.Println("in main package ... main")

	// 在函数调用的时候前面要定位到所在的包
	dbutils.GetConn()
	dbutils.Xixi()
	dbutils.Haha()
	
	// 注意,无法调用hehe函数,因为该函数并不对外哟~如果想要访问,则需要将其首字母大写哟~
	// dbutils.hehe()

	// 注意,由于我上面在导入包的时候使用了别名技术,因此不能直接使用utils,而是使用别名yinzhengjie进行调用
	// utils.Xixi()
	// utils.Haha()
	// utils.Add()

	yinzhengjie.Xixi()
	yinzhengjie.Haha()
	yinzhengjie.Add()
}

5 运行程序

如上图所示,直接执行"go run main.go"就可以看到测试结果啦~

三.包的细节说明

- 1.package用于进行包的声明,推荐包的声明和这个包所在的文件夹同名;

- 2.main包是程序的入口包,一般main函数会放在这个包下;

- 3.包定义语法为"package packagename";

- 4.导包的语法为"import packagename",导包的包名是从"$GOPATH/src/"后开始计算的,使用"/"进行路径分隔;

- 5.导包路径不推荐使用中文;

- 6.如果有多个包建议一次性导入,当然你也可以使用"import"关键字逐行导入每个包;

- 7.函数名,变量名,常亮名称等标识符首字母大写,这些标识符才可以被其他包访问,否则小写的标识符不能被其他包访问;

- 8.一个目录下不能有重复的函数;

- 9.包名和文件夹的名字,可以不一样,但是导包是必须时文件夹的路径,调用时使用包名称即可;

- 10.一个目录下的同级文件归属于一个包,换句话说,就是同一个目录下的"*.go"源代码文件不能同时声明是隶属于多个包,必须统一;

- 11.包在程序层面上是使用相同"package packagename"的源文件组成的代码模块,在源文件层面就是一个文件夹;

- 12.可以给包取别名,取别名后,原来的包名就不能使用了;

- 13.如果引入一个包的时候为其设置了一个特殊"_"作为包名,那么这个包的引入方式就称为匿名引入。

- 14.Go语言中禁止循环导入包; 
posted @ 2024-07-14 07:18  尹正杰  阅读(35)  评论(0编辑  收藏  举报