Go中的包以及函数/变量的可见范围 | Let’s GO

Go 做棵大树 1年前 (2023-03-26) 422次浏览 0个评论
文章目录[隐藏]

Go 中的包以及函数/变量的可见范围

看了上一篇函数的内容,可以发现漏掉了一个点,就是 函数可见范围

在 Java 中,我们可以通过 private protected public 快速的区分,但是到了 Go 没有这些关键字了。我一脸懵逼,要如何区分呢?

如何创建包

首先我们要知道 可见范围 的重点在于 范围,那Go中如何去界定这个范围的边界呢?这个就在 的定义。

和 Java 语言中类的定义不同,在 Go 中,多个文件只要在一个包下,其实可以看作是 Java 中一个类。这里我们同样列出代码。

我们新建 2 个目录, 3 个文件如下:

Go 中的包以及函数/变量的可见范围 | Let's GO

// visible1.go
package visible

var a int = 1
var A int = 100

func getSmallA() int {
 return a
}

func GetBigA() int {
 return A
}
// visible2.go
package visible

var A int = 123              // 报错,因为已经被定义了

func GetBigA() int {         // 报错
 return A
}

func geta() int {
 a := 123;                   // 不报错
 return a
}

如上代码所示,加上我们之前知道的规范:Go语言里,同一个目录下的包名需要一致 可知,我们新建一个目录,取了一个包名,那就已经完成了一个包的创建。

接下来我们会对 同一个 package 内不同 package 内 的访问展开叙述。

同一个 package(包内)

当我们在 visible2.go 文件中定义同名的变量或者方法时,编译器会提示报错:

  • GetBigA redeclared in this block compiler [DuplicateDecl] visible1.go(10, 6): other declaration of GetBigA

我们定义的 A 也会报相同的错误,但是在 geta 函数中的 a 却不会。这是因为他们的作用域不同,一个是 全局变量,一个是 局部变量

局部变量仅生效于自身所在的块内,而全局变量则可以作用于整个 package 甚至 package 外部。

因此我们知道同一个 package 下,它们是共享变量定义的,不允许同一 package 下 、同一作用范围内出现重复定义的变量和方法。所以也是我上边说的同一个 package 下的多个文件,类似于 Java 的一个类。(不足之处欢迎指正哈)

我们可以通过 go build 命令来检查代码是否能正常编译, 该命令不会直接生成可执行的代码。

不同 package (包外)

那在 package 外,Go 是怎么控制访问范围的呢?我们如果想要访问上边的 A 要如何访问呢?

首先说 Go 是如何控制访问范围的。

Go 没有提供 publicprivate 关键字,用于标明是否可以从包的内外部调用变量或函数。 但 Go 须遵循以下两个简单规则:

  • 如需将某些内容设为 专用内容,请以 小写字母 开始。≈ private
  • 如需将某些内容设为 公共内容,请以 大写字母 开始。≈ public

反过来,我们再看 visible1.go 中的代码可以发现,其中的 a 变量就是不能出包的,而 A 变量则可以在包外被访问。

当然,我们想要访问 visible 目录下的变量或者方法并没有这么简单,在此之前,我们要创建模块

Go 模块通常包含可提供相关功能的包。 包的模块还指定了 Go 运行你组合在一起的代码所需的上下文,例如编写代码时所用的 Go 版本。

例如我们要为 visible 包创建对应的模块,我们需要先到它的目录 visible\ 下,然后执行 go mod init 模块名称 命令创建对应模块的包

go mod init beatree/visible/visible

执行完成后会在目录下新增 go.mod 文件

Go 中的包以及函数/变量的可见范围 | Let's GO

文件内容如下:

module beatree/visible/visible

go 1.20

我们现在来看 visibleMain.go 的代码

package main

import (
 "beatree/visible/visible"         // 引入 visible 模块
 "fmt"
)

func main() {
 // fmt.Println(visible.a);                  // a not exported by package visible
 // fmt.Println(visible.getSmallA());        // getSmallA not exported by package
 fmt.Println(visible.A);
 fmt.Println(visible.GetBigA());
}

在 Go 中,包名称需遵循约定。 包使用其导入路径的最后一部分作为名称。在代码中我们可以看到,小写字母开头的变量和方法都无法被访问到。而大写的则可以。

就在运行时,大树踩了另一个坑:

visibleMain.go:4:2: package beatree/visible/visible is not in GOROOT (D:\CodeTime\******\visible\visible)`

这是怎么回事儿呢?下篇文章再说吧~


做棵大树 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明Go 中的包以及函数/变量的可见范围 | Let’s GO
喜欢 (0)
[欢迎投币]
分享 (0)
关于作者:
一个整天无所事事的,有时候忽然热血的孩子
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址