我是C语言的新手,看着Go的源代码树,我发现了这一点:
https://code.google.com/p/go/source/browse/src/pkg/runtime/race.c
void runtime∕race·Read(int32 goid, void *addr, void *pc); void runtime∕race·Write(int32 goid, void *addr, void *pc); void runtime·raceinit(void) { // ... }
斜杠和点(·)是什么意思?这是有效的C吗?
重要更新: 最终的答案* 肯定是您 *在golang-nuts邮件列表中 从 Go的作者之一 Russ Cox 获得的。就是说,我将在下面留下我的一些早期笔记,它们可能有助于您理解某些内容。 另外,通过阅读上面链接的答案,我相信在比我在下面测试过的版本更高的Go C编译器中,∕“伪斜杠”现在也可以转换为常规/斜杠(例如将中点转换为点)。但我没有时间去验证。
重要更新:
最终的答案* 肯定是您 *在golang-nuts邮件列表中 从 Go的作者之一 Russ Cox 获得的。就是说,我将在下面留下我的一些早期笔记,它们可能有助于您理解某些内容。
另外,通过阅读上面链接的答案,我相信在比我在下面测试过的版本更高的Go C编译器中,∕“伪斜杠”现在也可以转换为常规/斜杠(例如将中点转换为点)。但我没有时间去验证。
∕
/
该文件由Go语言套件的内部C编译器进行编译,该内部C编译器起源于Plan 9 C编译器(1)(2),并且与C标准有一些区别(主要是扩展名AFAIK)。
扩展之一是,它允许标识符中使用UTF-8字符。
现在,在Go Language Suite的C编译器中,对中点字符(·)进行了特殊处理,因为它被转换为目标文件中的常规点(。),由Go Language Suite的内部链接器解释为名称空间分隔符字符。
例 对于以下文件example.c(注意:它必须另存为UTF-8,不带BOM): ·Bar1(){} 无效foo·bar2(){} 无效foo ∕ baz·bar3(){} 内部C编译器产生以下符号: $ go工具8c example.c $ go工具nm example.8 T“” .Bar1 T foo.bar2 T foo ∕ baz.bar3 现在,请注意,我给了·Bar1()一个大写字母B。这是因为这样,我可以使它对常规的Go代码可见- 因为它被转换为与编译以下Go代码所产生的符号完全相同的符号: 包装实例 func Bar1(){} // nm将显示:T“” .Bar1
对于以下文件example.c(注意:它必须另存为UTF-8,不带BOM):
example.c
·Bar1(){} 无效foo·bar2(){} 无效foo ∕ baz·bar3(){}
内部C编译器产生以下符号:
$ go工具8c example.c $ go工具nm example.8 T“” .Bar1 T foo.bar2 T foo ∕ baz.bar3
现在,请注意,我给了·Bar1()一个大写字母B。这是因为这样,我可以使它对常规的Go代码可见- 因为它被转换为与编译以下Go代码所产生的符号完全相同的符号:
·Bar1()
B
包装实例 func Bar1(){} // nm将显示:T“” .Bar1
现在,关于您在问题中命名的功能,故事将进一步深入到兔子洞中。我不太确定自己是否会在这里,但我会根据我所知道的情况进行解释。因此,此点以下的每个句子都应读为好像在结尾处写有“ AFAIK ”。
因此,需要更好地理解这个难题的下一个缺失部分是,进一步了解奇怪的""名称空间以及Go套件的链接程序如何处理它。该""命名空间是我们可能要调用一个“空”(因为""一个程序员机构“的一个空字符串”)命名空间,或者也许更好,一个“占位符”命名空间。当链接器看到这样的导入时:
""
import examp "path/to/package/example" //... func main() { examp.Bar1() }
那么它将获取$GOPATH/pkg/.../example.a库文件,并在导入阶段即时""用替换每个文件path/to/package/example。因此,现在,在链接程序中,我们将看到如下符号:
$GOPATH/pkg/.../example.a
path/to/package/example
T路径/到/包装/示例.Bar1