公共的,私有的 - 大写,小写:

49

对于 GoLang 新手,来自 Delphi、C++:

我第一次尝试在 Go 中创建自己的包,按照如何布置工作区等所有说明操作,但我不断地遇到编译器错误:

./myPackage.go:52: undefined: myFunc

我稍微研究了一下,发现在Go语言中,公共访问修饰符只需通过将函数声明为大写字母即可实现。不错。

但当我开始尝试容器类(以List为例)时,我发现必须像这样声明一个List引用返回值:

func GetFactors(value *int64) *list.List {...

*list的字母要小写。

当我声明了一个指向列表的本地引用时,也是同样的:

l := list.New()

再次强调,list应为小写。

所以我很困惑。规则是什么?列表的调用和引用显然是公开的,否则我就无法调用/使用它们——那么为什么它们要写成小写字母呢?


您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - VonC
3个回答

54
在这种情况下,list是包的名称,你通过import "container/list"导入它,并且它的公有成员都是大写的,例如List
规则是公有函数、类型等应该大写。
你可以随意给导入的包取别名,但默认情况下它只是包路径的最后一部分的名称--在这种情况下,list
更新:它不是包路径的最后一部分。它是实际的包名(通常是相同的)。

1
明白了 - 谢谢。最让我困惑的是_list.New()_ - 它看起来像是在 C++ 中对列表类型的调用 - 如果是这样,它必须是公共的。所以你的意思是它实际上是对包的引用,而 New() 是该包中的一个独立函数,它自动返回一个 *List 引用,因为这就是列表包中 New() 的作用。有道理。这也澄清了文档中让我困惑的一些东西。 - Vector
是的。文档实际上非常适合探索——函数名称可以直接链接到源代码,有时阅读源代码比阅读文档更有用。 :) http://golang.org/src/pkg/container/list/list.go?s=1662:1678#L52 - Eve Freeman
3
我仍在摸索文档的使用方法,但开始发现它们非常有用 - 您的答案将对我很有帮助。Go 语言看起来像 C/C++,但实际上非常不同,这是一个具有误导性的事实。 - Vector

18
注意:从Go 1.5(2015年第二季度/第三季度)开始,您也将获得“受保护”的导入(命名为“internal”)!
请参见Go 1.4文档
Go的包系统使得将程序结构化为具有清晰界限的组件变得容易,但是只有两种访问形式:本地(未导出)和全局(已导出)。有时候,人们希望拥有不导出的组件,例如避免客户端获取接口代码,这些代码是公共存储库的一部分,但不打算在所属程序之外使用。Go语言没有强制执行此区别的能力,但自Go 1.4以来,go命令引入了一种定义“内部”包的机制,这些包不能被其所在源子树之外的包导入。要创建这样的包,请将其放置在名为internal的目录中或名为internal的目录的子目录中。当go命令看到路径中带有internal的包的导入时,它会验证进行导入的包是否在父级internal目录的根目录下的树中。例如,包.../a/b/c/internal/d/e/f只能由位于.../a/b/c目录树中的代码导入。它不能被.../a/b/g或任何其他存储库中的代码导入。对于Go 1.4,内部包机制适用于主Go存储库;从1.5开始,它将适用于任何存储库。

我不熟悉Java中的保护级别,但在C#中有protected仅将成员公开给派生类,而internal将成员公开给本地包。我认为成员应该被完全隐藏,而不是在访问之前执行验证。 - Shimmy Weitzhandler

8
注意:Go规范中关于包名的说明并没有提到包名总是小写的事实。
它只声明其名称由一个 标识符表示,该标识符由一系列 "字母" 组成。 这个帖子解释道:
“包名可以是任何东西,如果您愿意,可以以大写字母开头。但是惯例是全部小写,这样可以避免输入大写字母的麻烦。”
“大写字母/小写字母的可导出性与包没有真正的关系,因为您不能拥有私有包。”
了解了这些,就更容易认出:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接