英文:
Public, Private - Upper Case, Lower Case:
问题
新手学习Go语言,之前使用Delphi和C++。第一次尝试在Go中创建自己的包时,我按照关于如何布置工作空间等的所有说明进行了操作,但是一直遇到编译错误:
./myPackage.go:52: undefined: myFunc
经过一番探索,我发现在Go中,通过将函数声明为大写来实现公共访问修饰符。很好。
但是当我开始尝试使用容器类(例如List
)时,我发现我必须像这样声明一个返回值为List引用的函数:
func GetFactors(value *int64) *list.List {...}
*list
是小写的。
当我声明一个本地引用列表时,我必须使用:
l := list.New()
同样,list
是小写的。
所以,我感到困惑。规则是什么?显然,列表的调用和引用是公共的,否则我就无法调用/使用它们,那为什么它们是小写的呢?
英文:
New to GoLang, coming from Delphi, C++ :
First time I tried to create my own package in Go, I followed all the instructions about how to lay out the workspace, etc, but I kept on getting a compiler error:
./myPackage.go:52: undefined: myFunc
After poking around a bit I discovered that the public access modifier in Go is achieved simply by declaring a function in upper case. Great.
But when I started experimenting with the container classes - List
for starters, I discovered I had to declare a List reference return value like this:
func GetFactors(value *int64) *list.List {...
*list
is in lower case.
Same when I declared a local reference to a list - I had to use:
l := list.New()
Again, lower case for list
.
So, I'm confused. What is the rule? The list calls and references are obviously public, or I wouldn't be able to call/use them - so why are they in lower case?
答案1
得分: 54
在这种情况下,list
是包的名称,你通过import "container/list"
导入它,它的公共成员是大写的,比如List
。
规则是公共函数、类型等应该是大写的。
你可以根据需要给导入的包起别名,但默认情况下它只是包路径的最后一部分的名称——在这种情况下是list
。
更新:它不是包路径的最后一部分,而是实际的包名(通常是相同的)。
英文:
In this case, list
is the name of the package, which you are importing via import "container/list"
, and its public members are upper case, like List
.
The rule is that public functions, types, etc., should be upper case.
You can alias imported packages however you want, but by default it is just the name of the last part of the package path--in this case, list
.
Update: It's not the last part of the package path. It's the actual package name (which is often the same thing).
答案2
得分: 18
注意:从Go 1.5(2015年第二季度/第三季度)开始,您还将获得“protected”导入(命名为“internal”)!
请参阅Go 1.4文档:
Go的包系统使得将程序结构化为具有清晰边界的组件变得容易,但只有两种访问形式:本地(未导出)和全局(导出)。
有时,我们希望拥有不导出的组件,例如避免获取接口的客户端代码,这些代码是公共存储库的一部分,但不打算在其所属程序之外使用。
Go语言没有强制执行此区分的能力,但从Go 1.4开始,
go
命令引入了一种定义“internal”包的机制,这些包不能被其所在源子树之外的包导入。
要创建这样的包,请将其放置在名为
internal
的目录中或者放置在名为internal
的目录的子目录中。
当go
命令看到导入路径中带有internal
的包时,它会验证进行导入的包是否在父目录为根的树中。
例如,包.../a/b/c/internal/d/e/f
只能被.../a/b/c
目录树中的代码导入。
它不能被.../a/b/g
目录中的代码或任何其他存储库中的代码导入。
对于Go 1.4,内部包机制仅在主Go存储库中强制执行;
从1.5版本开始,它将在任何存储库中强制执行。
英文:
Note: starting Go 1.5 (Q2/Q3 2015), you will get "protected" import as well (named "internal")!
See Go 1.4 doc:
> Go's package system makes it easy to structure programs into components with clean boundaries, but there are only two forms of access: local (unexported) and global (exported).
Sometimes one wishes to have components that are not exported, for instance to avoid acquiring clients of interfaces to code that is part of a public repository but not intended for use outside the program to which it belongs.
> The Go language does not have the power to enforce this distinction, but as of Go 1.4 the go
command introduces a mechanism to define "internal" packages that may not be imported by packages outside the source subtree in which they reside.
> To create such a package, place it in a directory named internal
or in a subdirectory of a directory named internal
.
When the go
command sees an import of a package with internal
in its path, it verifies that the package doing the import is within the tree rooted at the parent of the internal directory.
For example, a package .../a/b/c/internal/d/e/f
can be imported only by code in the directory tree rooted at .../a/b/c
.
It cannot be imported by code in .../a/b/g
or in any other repository.
> For Go 1.4, the internal package mechanism is enforced for the main Go repository;
from 1.5 and onward it will be enforced for any repository.
答案3
得分: 8
注意:Go规范中关于包名并没有提到包名总是小写的。它只说明包名由一个由“字母”组成的标识符表示。
这个讨论串进行了澄清:
包名可以是任何东西,如果你愿意,可以以大写字母开头。
但是惯例是全部小写,我猜这样可以省去输入大写字母的麻烦。
大写/小写的可导出性对于包来说并不重要,因为你不能有一个私有包。
一旦你知道了这一点,就更容易识别:
-
list.New()
是一个**构造函数**(总是在包级别上,用于构建一个已初始化的类型实例),就像os.NewFile()
一样, -
list.List
是包list
的结构类型(该包的另一个结构类型是list.Element
)。
英文:
Note: the Go Spec for package name don't mention that a package name is always in lowercase.
It only state that its name is represented by an identifier, which is composed of a collection of "letter".
This thread does clarify:
> Package names can be anything, you can start them with an uppercase letter if you want to.
But the convention is all lowercase, which I guess saves you the hassle of typing an uppercase letter.
> The uppercase/lowercase exportability isn't really relevant to packages since you can't have a private package.
Once you know that, it is easier to recognize:
-
list.New()
for a constructor (always at the package level, to build an initialized instance of a type), likeos.NewFile()
, -
list.List
for a struct type of the package list (the other struct type of that same package beinglist.Element
).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论