包裹声明的目的是什么?

时间:2016-07-25 09:21:58

标签: go

每个Go文件都以package <something>开头。

据我所知 - 这可能是我遗漏了一些信息的地方 - <something>只有两个可能的值:它所在的目录名称*或main。如果是main,则该目录中的所有其他文件也只能有main。如果是其他内容,则项目不一致/违反惯例。

现在,如果它是目录的名称,那就是多余的,因为相同的信息也是在目录的名称中。

如果是main,那就没用了,因为据我所知,没有办法告诉go build“请建立所有 {{1包裹“。

*因为,换句话说,一个目录是一个包。

2 个答案:

答案 0 :(得分:8)

您缺少的信息&#34;是包名称不必与目录名称相同。

使用文件夹名称以外的包名称是完全正确的。如果这样做,您仍然必须根据目录结构导入包,但在导入后,您必须通过在package子句中使用的名称来引用它。

例如,如果您有一个文件夹$GOPATH/src/mypck,并且其中有一个文件a.go

package apple

const Pi = 3.14

使用此包:

package main

import (
    "mypck"
    "fmt"
)

func main() {
    fmt.Println(apple.Pi)
}

就像您被允许使用相对导入但不可取,您可以使用其他包含文件夹的包名,但这也不建议避免进一步的误解。

请注意,规范甚至不要求属于同一个包的所有文件都在同一个文件夹中(但它可能是实现要求)。 Spec: Package clause:

  

一组共享相同PackageName的文件形成包的实现。实现可能要求包的所有源文件都位于同一目录中。

使用了什么?

简单。包名称是Go identifier

identifier = letter { letter | unicode_digit } .

允许在标识符中使用unicode字母,例如αβ是Go中的有效标识符。 Go不是处理文件夹和文件名,而是由操作系统处理,不同的文件系统有不同的限制。实际上有许多文件系统不允许所有有效的Go标识符作为文件夹名称,因此您将无法为您的软件包命名,否则语言规范将允许。

因此,一方面并非所有有效的Go标识符都可能是有效的文件夹名称。另一方面,并​​非所有有效的文件夹名称都是有效的Go标识符,例如go-math在大多数(所有?)文件系统中是有效的文件夹名称,但它不是有效的Go标识符(如标识符不能包含短划线-字符。)

可以选择使用与其包含文件夹不同的软件包名称,您可以选择真正命名软件包规范允许的软件包,无论底层操作和文件系统如何,并将其放在名为“底层操作系统和文件系统允许 - 无论包名称如何。

答案 1 :(得分:7)

包的名称不必与目录名一致。目录package foobar中可以有xyz/go-foobar。在这种情况下,xyz/go-foobar会成为导入路径,但您用来标记标识符(函数,类型等)的包名称将是{{ 1}}。

以下是一个更具体的示例:我创建了一个测试包http://godoc.org/github.com/dmitris/go-foobar(来自https://github.com/dmitris/go-foobar) - 您可以从文档页面看到,导入路径是& #34; github.com/dmitris/go-foobar"但程序包名称为foobar,因此您可以将其提供的函数称为foobar(而不是foobar.Demo())。

类似的现实例子 - NSQ Messaging平台的导入路径是&#34; github.com/nsqio/go-nsq"虽然包名是&#34; nsq&#34;:http://godoc.org/github.com/nsqio/go-nsq。但是,为了用户友好性和简单性,标准和建议的做法是尽可能保持导入路径的最后部分和包名称相同。

go-foobar.Demo()没有用 - 它告诉Go编译器创建一个可执行文件而不是.a库文件(package maingo install; go get丢弃编译结果)。可执行文件以放置go build文件的目录名命名。再一个具体的例子 - 我制作了一个测试程序https://github.com/dmitris/go-foobar-client,你用package main安装它,你应该得到一个go get github.com/dmitris/go-foobar-client可执行文件放在你的$ GOPATH / bin目录中。它来自放置go-foobar-client文件的目录名,Go编译器从中获取可执行文件的名称。包含package main函数的.go文件的文件名并不重要 - 在上面的示例中,我们可以将main()重命名为main.go或其他内容,但只要封闭目录名为client.go,它是如何命名生成的可执行文件。

关于Go套餐的其他可访问性和实用性的阅读,我推荐Dave Cheney的文章&#34;建立Go项目的五个建议&#34; http://dave.cheney.net/2014/12/01/five-suggestions-for-setting-up-a-go-project