✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑
文章目录
Go语言中的包
在Go语言中,包(Package)是组织和管理代码的基本单元。通过合理地使用包,我们可以提高代码的复用性、可维护性和可读性。
1. 包的定义
Go语言中包的本质:文件夹,不同的文件夹可以存放不同的功能代码。
在Go语言中,每个源代码文件都必须属于一个包。包通常由一个或多个以.go为后缀的源文件组成,这些源文件通常存放在同一个目录下。
包的名称应该具有描述性,能够清楚地表达其功能。包名一般使用小写字母,并且和包所在的文件夹名保持一致。
2. 包的可见性
Go语言使用大小写来控制代码的可见性。以大写字母开头的标识符(变量、函数、类型等)可以被其他包导入并使用,称为导出的标识符;而以小写字母开头的标识符只能在当前包内部使用,称为私有的标识符。
创建一个新的包
首先,我们需要创建一个新的目录来存放包的文件。目录的名称即为包的名称。然后,在该目录下编写相应的.go文件,并在文件的第一行使用package关键字声明该文件的包名。
3. go语言main包和package介绍
main包
1、main函数所在的包,必须是main包。代表程序的入口。整个项目只能有一个main函数,否则在main函数里面右键build项目的时候会报错
2、main包中引入其他包 ,import “fmt”
3、main是程序的入口,其他包不能使用,尽量使用网址作为包名。
4、不建议自己定义一个main文件夹用来存放main.go 一般main.go 以文件方式放到程序的工作目录。不建议其他包使用main文件夹
package
src:保存我们项目的源码路径,所有的代码都用包的形式放在这里。
package 声明包在哪里,不需要和文件夹名一致,但是我们尽量使用文件夹的名字。
1、一个目录下所有的go文件的用package指定的包名必须同名。
2、package指定的包名可以和文件夹不同名,但不建议这么写。
3、同一个包下的所有go文件的函数,可以直接调用。
4、导入包的时候,除了系统自带的包,导入我们自己写的包要从goworks目录下的src去写。
5、对于外包中的函数,我们需要使用我们导入的包名.函数名来使用。如果当前包的函数或者字段要给外面的包使用,首字母必须大写。
user.go中的UpdateUser函数要给userService.go中使用
导包调用
我们看下我们安装的go
也包含src pkg bin等文件夹
bin下就是我们执行go gofmt命令的可执行文件
src下就是go语言的源码包
作为对比,我们写的代码就在GOPATH=F:\goworks 设置的goworks目录下的src目录下
4. 常见的导包方式
1、批量导入包
import(// 系统包""// 自己写的包 ..""// 网上下载的包 github..."")
2、相对路径导入包 …/ 上一级
import"../xxx"// 不建议这样用
3、如果包名冲突,解决办法。
- 可以给包起别名,在包的前面给个字段就是起别名
- 简便模式:导入包里面的函数,前面加个点. 可以直接调用该包下的函数,不需要通过包名。
- 匿名导入,在导入的包前面加 _ 只会执行这个包下所有的init方法
package service
// 包////import "math/rand" // 随机数生成import(//R "math/rand" // 可以给包起别名,在包的前面给个字段就是起别名//. "math/rand" // 简便模式:导入包里面的函数,前面加个点. 可以直接调用该包下的函数,不需要通过包名。_"math/rand"// 匿名导入,在导入的包前面加 _ 只会执行这个包下的init方法)functest(){}
5. 包的初始化
在Go语言中,每个包在被导入时,其中的全局变量以及init函数(如果有的话)会被自动执行。init函数的作用类似于构造函数,用于执行一些初始化操作。
要匿名导入 _ “math/rand” // 匿名导入,只会执行这个包下的init方法
Go语言中,除了main函数入口以外,还有一个十分特别的函数 init()函数。
init:初始化,在main方法执行之前执行
init:设置一些包… 初始化一些全局变量… 建立一些第三方的连接(数据库连接)、注册、检查、修复程序状态。
init 函数可以有多个,在同一个go文件中可以重名。
init 函数不需要传入参数,也没有返回值,任何地方不能调用 init()
init() 函数不能使用延迟函数 defer
init() 函数的用途:
初始化包或模块的全局变量。
注册自定义函数或类型。
执行其他初始化操作。
1. init函数的执行顺序问题
匿名导入包,会执行包下所有go文件的 init 函数, 单个init被多个地方导入,只会执行一次
1、先执行导入包的init函数,单个go文件中是顺序执行的,所有go中的init函数执行完毕后,才会到main包
2、如果导入了多个匿名包,按照main中导入包的顺序来进行执行。
3、在同一个包下的go文件如果有多个,都有init的情况下,按照文件从上到下排放顺序来执行对应的init函数()
代码展示
main.go
package main
//匿名导入import("fmt"_"jingtian/包的初始化/myinit"_"jingtian/包的初始化/secondinit")funcinit(){
fmt.Println("main---init")}funcmain(){// init 函数不需要传入参数,也没有返回值,任何地方不能调用 init()//init()}
a.go
package myinit
import"fmt"// 匿名导入包,会执行报下所有go文件的 init 函数, 单个init被多个地方导入,只会执行一次// 1、先执行导入包的init函数,单个go文件中是顺序执行的,所有go中的init函数执行完毕后,才会到main包// 2、如果导入了多个匿名包,按照main中导入包的顺序来进行执行。// 3、在同一个包下的go文件如果有多个,都有init的情况下,按照文件排放顺序来执行对应的init函数()funcinit(){
fmt.Println("a--init1")}funcinit(){
fmt.Println("a--init2")}funcinit(){
fmt.Println("a--init3")}
b.go
package secondinit
import_"jingtian/包的初始化/myinit"
运行main,可以看到虽然myinit在main.go 和 b.go中都有导入,但是只执行了一次
而且是先执行完导入的包里面的init函数,然后才执行main里面的init函数
2. 执行顺序流程图
被依赖的包的init()函数会先于依赖它的包的init()函数执行。
版权归原作者 景天科技苑 所有, 如有侵权,请联系我们删除。