【问题标题】:Clarify definition of exported identifier明确导出标识符的定义
【发布时间】:2025-12-17 14:00:02
【问题描述】:

Go specification to define an identifier 导出的基本原理是什么

如果两者都有:

  1. 标识符名称的第一个字符是 Unicode 大写字母(Unicode 类“Lu”);和
  2. 标识符是在包块中声明的,或者是字段名或方法名。 "

第 1 项我很清楚。

但是第 2 项的预期含义是什么?

据我所知,每个标识符都必须在包块中声明,因为 Go 不提供其他地方来声明标识符。 我也不明白为什么这句话似乎区分标识符和字段名和方法名。字段名和方法名不是标识符的例子吗?

换个方式问:我这样想是不是错了:

  1. 没有其他方法可以让标识符存在,除非 在包块中声明(注意a package block encompasses all package code
  2. 字段名和方法名是标识符
  3. 标识符只能在包块中声明
  4. 没有在包块外声明标识符

【问题讨论】:

  • “除了在包块中声明之外,还有其他方法可以让标识符存在吗?”是的当然。例如,函数或方法中的局部变量。 "Identifiers name program entities such as variables and types." 类型也可以在函数中声明,它们不必在包块中。
  • @Peter:我认为这不是一个很好的例子。您命名的所有实体仍在“包块”中。请参阅golang.org/ref/spec#Blocks 中“包块”的定义:“每个包都有一个包块,其中包含该包的所有 Go 源文本。”
  • “Go source text”不是“所有标识符”的同义词。 "Declarations and scope" 部分详细描述了标识符如何绑定到块。例如:“5. 在函数内声明的常量或变量标识符的范围从 ConstSpec 或 VarSpec [...] 的末尾开始,并在最里面的包含块的末尾结束。 "
  • "没有标识符可以在同一个块中声明两次。"如果您的理解是正确的,那么您永远不能两次使用相同的变量名,因为它们会在 Universe 块中发生冲突。显然不是这样的。

标签: go


【解决方案1】:

标识符包括结构字段名和方法名。

struct types 部分所述:

可以显式(IdentifierList)或隐式指定字段名称 (嵌入式字段)

在以下结构中:

type s struct {
  A int
  b int
}

A 被导出,因为它是一个字段名称并且以大写字符开头。 b 不是,因为它是一个字段名,但不是以大写字符开头。

方法名称也是如此(例如:(_ s) DoA()(_ s) doB())。

混淆源于您认为标识符仅在包块级别:它们不是。

【讨论】:

  • 感谢您尝试回答。您能否详细说明这里的“块级别”是什么意思?如果你的意思是'}'包围的代码块,'{',例如函数体或 for/if 构造' - 那么不,我不会将我的想法局限于这些。我也考虑例如包级变量。顺便说一句:在您的示例结构声明中,您使用了 some 块(用 '}'、'{' 分隔)——尽管您似乎暗示块级思维在这里过于狭窄。
【解决方案2】:

1。除了在包块中声明之外,没有其他方法可以使标识符存在

确实如此。您缺少的一件事是 scope 的标识符:

在函数内声明的常量或变量标识符的范围从 ConstSpec 或 VarSpec(短变量声明的 ShortVarDecl)的末尾开始,到最里面的包含块的末尾结束

这意味着在功能块内声明的标识符在此功能之外将不可用。

2。字段名和方法名是标识符

没错。正如您在规范中看到的,MethodName 只是identifier 的别名,与field names 相同。

3。标识符只能在包块中声明

我相信这是通过回答第一个问题来解决的。

4。不能在包块外声明标识符

在 Universe 块中声明了 predeclared identifiers。但是你不能在代码中的包块之外声明标识符。

【讨论】: