Go语言基础之包

Go语言基础之包

前言

Hey,大家好呀,我是星期八,咱们原来写的代码,都是缩在一块的,久而久之咱们可能都能感觉到冗余。

所以今天就来学一下包这个东西,将咱们的代码拆分一下。

包可以理解为存放多个.go的文件夹但是这个文件夹下面的第一行的package后面跟的不再是main了而是文件名

就像这样。

目录

在这里插入图片描述

clacmain.go文件是同级的。

可以看到clac文件夹下的add.go第一行不再是main而是文件夹名 clac同理sub.go第一行也是。

这个只是单独的解释包的定义方式没有实际意义。

包的注意事项

如果这个文件夹要当包使用文件夹名中不能包含_

导入包

上面我们知道了包是如何定义的。

并且在和main.go同级的项目目录下建了一个clac包。

clac包下有俩个文件一个是add.go一个是sub.go两个文件夹分别都有对应的方法

问题???

那我们如何在main.go中使用上述建立的包调用里面的方法呢?

这就是要导入他们了。

示例代码

package main

import (
   "a3_course/clac"
)

func main() {
   clac.Add()
   clac.Sub()
}

执行结果

在这里插入图片描述

可以看到在main.go中成功调用了clac包中的代码。

**注:**导入包只需要导入到文件夹即可就可以调用下面所有的方法和属性不再需要包名.xx.go这种方式。

如上述导入calc不管calc下面有几个.go文件里面的方法和属性都可以随便调用。

导入包注意事项

上述我是直接通过

import (
   "a3_course/clac"
)

这种方式导入包的但是在你们那可能不太行。

因为我使用的时go mod所以通过项目目录/包名导入。

在这里插入图片描述

如果你没有使用go mod是传统的方式那么导入包需要从GOPATH/src进行导入这里不举例了。

如果还不会使用go mod记得爬楼看以往文章上面有教程要拥抱未来。

可见性

可见性在其他语言中有的叫私有成员之类的称呼在Go中就叫可见性。

Go中可见性很简单不管是变量还是函数还是结构体。

首字母大写在哪都能访问。

首字母小写只能在当前包使用。

示例

clac/add.go文件

package clac

import (
	"fmt"
)

//这是一个公开的变量
var Name = "张三"

//这是一个私有变量,只能在 clac 包中访问
var age = 18

//这是一个公开的函数
func Add() {
	fmt.Println("我是做加法的...")
}

main.go文件

func main() {
	clac.Add()
	clac.Sub()
	fmt.Println(clac.Name)
	//clac中的age是小写开头,属于私有变量,所以其他包不能访问
	//fmt.Println(clac.age) // cannot refer to unexported name clac.age
}

访问私有变量报错信息。

在这里插入图片描述

结构体可见性的问题

我们知道结构体是有字段的但是你想过结构体的字段大小写问题吗?

type Student struct {
	Name string
	age  int
}
//age是小写开头

结构体名开头是不是大写影响的主要是在其他包里面的调用权限问题。

结构体字段开头是不是大写主要影响的是调用里面字段的问题一个明显的问题就是序列化。

示例代码

package main

import (
	"encoding/json"
	"fmt"
)

type Student struct {
	Name string
	age  int
}

func main() {
	var s1 = Student{
		Name: "张三",
		age:  18}
	serializeBytes,err:=json.Marshal(s1)
	if err != nil {
		fmt.Println("序列化失败")
	}
	serializeStr := string(serializeBytes)
	fmt.Println(serializeStr)
}

执行结果

在这里插入图片描述

会发现执行结果少了一个age

这是因为age小写开头属于私有变量。

但是json.Marshal(s1)这个已经属于其他包了所以访问不到age

包别名

我们在导入包时其实还可以自定义包名就像Python中的 from xx import xx as yy

示例代码

package main

//给 clac 包起别名
import cl "a3_course/clac"

func main() {
	cl.Add()
}

执行结果

在这里插入图片描述

匿名导入包

匿名导入包就是相当于不用这个包里面的东西。

可能有人就会问了那不用包里面的东西导它干毛。

嗯…这个匿名导入包主要要跟包的一个init方法有关系咱们先继续看。

匿名导入包示例代码

package main

//前面有个 _ 就表示是匿名导入
import _ "a3_course/clac"

func main() {

}

包的init方法

其实每次导入其他包的时候都会执行包的init方法。

示例

//clac/add.go
package clac

import "fmt"

func init() {
	fmt.Println("clac/add.go/init")
}
func Sub() {
	fmt.Println("我是做减法的...")
}

//clac/sub.go
package clac

import "fmt"

func init() {
	fmt.Println("clac/sub.go/init")
}
func Sub() {
	fmt.Println("我是做减法的...")
}

main.go

package main

import _ "a3_course/clac"

func main() {

}

执行结果

在这里插入图片描述

可以发现我虽然是匿名导入包但是仍然还是执行了add.gosub.go下的init方法。

这就说明了一个问题导入一个包会执行这个包下面所有的init方法不管下面有几个.go文件。

**注:**包的init方法不能写参数也不能有返回值init方法只能在导入时调用不能主动调用。

init方法比main方法更提前一步执行

多个包嵌套导入时init方法执行的顺序

代码较多就直接如图所示了

在这里插入图片描述

这意思是main.go导入了otherother包导入了inner包 ,套娃。

先看一下执行结果

在这里插入图片描述

执行结果是innerinit方法先执行然后是ohterinit方法。

其实本质是碰到import就执行被导入包的init方法。

他的图应该是这样子的。

在这里插入图片描述

意思是main导入了ohter那就执行otherinit方法。

但是在导入ohter时发现other导入了inner那就执行innerinit方法。

导入包注意事项

在目前情况下,一般开发的时候为了方便,都使用了go mod

如下,通过go mod init packageDemo生成了一个版本控制文件

go.mod

module packageDemo

go 1.14

实例项目
在这里插入图片描述

那我在main.go中,要如何导入项目目录下的其他包呢?

  • 项目名/包名?
  • 还是直接包名?

其实都不是,使用的是go mod init <名>,<名>/包名
在这里插入图片描述

我现在将这个名字改一下

在这里插入图片描述

所以,如果使用了go mod,导入自己的包,只跟go mod init后面跟的有关系,跟项目根文件夹没关系,

简而言之就是,go mod init后面跟的是啥,就相当于哪个啥是根目录,

如果使用的不是go mod,那我只能祝你好运了!

总结

上述我们学习了Go基础之包,学习了如何创建包组织包导入包的注意事项

包的权限问题(大写开头所有可见)匿名导入包init方法多个init方法注意事项。

可能有点不太好理解,但是还是要坚持,一定要多敲两次。

如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

我是码农星期八,如果觉得还不错,记得动手点赞一下哈。

感谢你的观看。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值