前言大家好,我周五了,我们原本写的代码都缩在了一起,时间一长大家可能都觉得多余了。那么今天就来学习打包,拆分我们的代码。package可以理解为一个存放多个.go文件的文件夹,但是这个文件夹下package的第一行后面不再是main而是文件名,就像这样。目录clac和main.go文件在同一层级。可以看到clac文件夹下的add.go第一行不再是main而是文件夹名。clac中sub.go的第一行也是如此。这只是对包定义的单独解释,没有实际意义。打包注意事项如果将此文件夹作为打包使用,文件夹名称不能包含_。导入包上面我们知道了包是怎么定义的。并在与main.go同级的项目目录下构建了一个clac包。clac包下有两个文件,一个是add.go,一个是sub.go。两个文件夹都有相应的方法。问题来了???那么我们如何使用上面创建的包来调用main.go中的方法呢?这是导入它们。示例代码packagemainimport("a3_course/clac")funcmain(){clac.Add()clac.Sub()}执行结果表明在main.go中成功调用了clac包中的代码。注意:导入包只需要导入到文件夹中就可以调用下面所有的方法和属性,不再需要包名.xx.go这样了。如上importcalc,不管calc下有多少.go文件有方法和属性,都可以随意调用。导入包的注意事项我上面说的直接通过import("a3_course/clac")导入了包,但是不一定适合你。按项目目录/包名称导入,因为我使用的是gomod。如果不用gomod,是传统方式,那么import包需要从GOPATH/src导入,这里就不举例了。如果你不会gomod怎么用,记得爬上楼看看之前的文章。上面有教程。一篇文章教你如何使用Go语言模块。记得拥抱未来。VisibilityVisibility在其他语言中被称为私有成员,但在Go中被称为可见性。Go中的可见性非常简单,无论是变量还是函数还是结构体。帽子可以在任何地方使用。小写首字母只能在当前包中使用。示例packageclacimport("fmt")//这是一个公共变量varName="张三"//这是一个私有变量,只能在clac包中访问varage=18//这是一个公共函数funcAdd(){fmt.Println("Iamdoingaddition...")}main.gofilefuncmain(){clac.Add()clac.Sub()fmt.Println(clac.Name)//clac中的age是Beginningwith小写,是私有变量,所以其他包无法访问//fmt.Println(clac.age)//cannotrefertounexportednameclac.age}访问私有变量,报错信息。结构体可见性的问题我们知道结构体是有字段的,但是你有没有想过结构体字段的大小写呢?typeStudentstruct{Namestringageint}//age以小写开头,结构名是否以大写开头,主要是受其他包中的调用权限问题。结构体字段开头是否大写主要影响调用里面字段的问题。一个明显的问题是序列化。更多关于结构体的文章,请访问:Go语言基础结构体(春日)示例代码packagemainimport("encoding/json""fmt")typeStudentstruct{Namestringageint}funcmain(){vars1=Student{Name:"张三",age:18,}serializeBytes,err:=json.Marshal(s1)iferr!=nil{fmt.Println("Serializationfailed")}serializeStr:=string(serializeBytes)fmt.Println(serializeStr)}执行结果,会发现执行结果少了一个age。这是因为age以小写字母开头,是一个私有变量。但是json.Marshal(s1)已经属于其他包,所以无法访问age。包别名我们其实可以在导入包的时候自定义包名,就像Python中的fromxximportxxasyy一样。示例代码packagemain//别名clac包importcl"a3_course/clac"funcmain(){cl.Add()}执行结果匿名导入包匿名导入包相当于不使用这个包里面的东西。可能有人会问,既然不需要包里的东西,为什么还要import呢?嗯……这个匿名导入包主要是和包的一个init方法有关。我们先继续看。匿名导入包示例代码packagemain//前面有一个_,表示import_"a3_course/clac"funcmain(){}包的init方法是匿名导入的。实际上,每次导入其他包时,都会执行该包的init方法。例子//clac/add.gopackageclacimport"fmt"funcinit(){fmt.Println("clac/add.go/init")}funcSub(){fmt.Println("Idosubtraction...")}//clac/sub.gopackageclacimport"fmt"funcinit(){fmt.Println("clac/sub.go/init")}funcSub(){fmt.Println("我做减法...")}main的执行结果.gopackagemainimport_"a3_course/clac"funcmain(){}显示虽然我匿名导入了包,但还是执行了add.go和sub.go下的init方法。这说明了一个问题。导入一个包,不管下面有多少个.go文件,都会执行这个包下的所有init方法。注意:包的init方法不能写参数,不能有返回值。init方法只能在导入时调用,不能主动调用。init方法比main方法早一步执行。多个包嵌套导入时,init方法执行的顺序代码比较多,如图:意思是main.go导入了另一个包。另一包进口内包,套娃。先看执行结果。执行结果是先执行内层的init方法,再执行其他的init方法。其实本质就是在遇到import的时候执行导入包的init方法。它的图表应该是这样的。意思是main导入ohter,然后执行other的init方法。但是在导入ohter的时候发现other导入了inner,然后执行inner的init方法。综上所述,我们已经学习了Go的基本包,如何创建包,组织包,导入包。包权限问题(都是大写开头可见),匿名导入包,init方法,多个init方法的注意事项。可能理解起来有点难,但是还是要坚持,一定要多打两遍。
