【问题标题】:How to specify the package name if multiple files exist in the package folder and one file contains the "package main"?如果包文件夹中存在多个文件并且一个文件包含“包主”,如何指定包名称?
【发布时间】:2017-04-13 14:15:42
【问题描述】:

假设我有一个如下的包文件夹:

hello
  |---main.go
  |---utilities.go

main.go,我有:

package main

utilities.go,我有:

package hello

我这样做是因为:

  • 我不想将所有实用程序放入单个main.go 文件中。
  • 而且这些实用程序仅供此软件包使用,因此我不想将其从 hello 文件夹中删除。

但是当我运行go list hello 时,它给了我这个:

无法加载包:包你好:找到包 main (main.go) 和 你好(utilities.go)在 E:\Workbench\Go\src\hello

然后我删除了utilities.go 并再次尝试了go list hello,只使用了main.go。它给了我这个:

你好

那么我是否必须将所有实用程序移动到另一个包文件夹?

我是否必须在 hello 包文件夹中只保留单个 main.go,因为它似乎与其他包名称不协调?

添加 1

一个有用的参考:http://thenewstack.io/understanding-golang-packages/

添加 2

经过一些简短的实验,我猜import yyy 决定了链接搜索路径,而package xxx 声明决定了编译后的.a 文件中导出的符号名称。

因为我注意到了这些事实:

  • package xxx 声明不必与包含的包文件夹名称相同,例如 yyy
  • import yyy声明必须使用包文件夹路径yyy
  • 使用包中的符号时,我们仍然必须使用xxx.Symbol 而不是yyy.Symbol

添加 3

为了确认我在 ADD 2 中的猜测,我这样做了:

(pkg1\file1.go)

package pkg2 // I deliberately use a different pkg name "pkg2" rather than the folder name "pkg1"

import "fmt"

func FA() {
    fmt.Println("in the pkg2.FA")
}

(cmd1\main.go)

package main

import "pkg1"

func main() {
    pkg2.FA() //here, the FA is referenced via "pkg2" rather than the "pkg1".
}

以上2个文件都可以编译运行。

但如果我改成这样:

(cmd1\main.go)

package main

import "pkg1"

func main() {
    pkg1.FA() //here, the FA is referenced via "pkg1" as in the import statement. Should work, isn't it?
}

这将给出:

....\src\cmd1\main.go:3:已导入但未使用:“pkg1”as pkg2

....\src\cmd1\main.go:6: undefined: pkg1 in pkg1.FA

为了再次确认,我检查了编译后的 pkg1.a 文件和 go tool nm pkg1.a我没有看到包名会影响导出的符号。 (顺便说一句,GNU nm 工具似乎无法识别 golang .a 文件格式。)

     U
 515 T %22%22.FA   <========== this is my fuction FA
 67b R %22%22.FA·f <========== this is my fuction FA
 5eb T %22%22.init
 67b B %22%22.initdone·
 683 R %22%22.init·f
     U fmt.Println
     U fmt.init
 673 R gclocals·33cdeccccebe80329f1fdbee7f5874cb
 66b R gclocals·69c1753bd5f81501d95132d08af04464
 65b R gclocals·e29b39dba2f7b47ee8f21f123fdd2633
 64d R go.string."in the pkg2.FA"
 63d R go.string.hdr."in the pkg2.FA"
 7d2 R go.typelink.*[1]interface {}
 796 R go.typelink.[1]interface {}
 737 R go.typelink.[]interface {}
     U runtime.algarray
     U runtime.convT2E
 6ec R runtime.gcbits.01
 68b R runtime.gcbits.03
     U runtime.morestack_noctxt
     U runtime.throwinit
 79a R type.*[1]interface {}
 7d6 R type..importpath.fmt.
 73b R type..namedata.*[1]interface {}.
 6ed R type..namedata.*[]interface {}.
 68c R type..namedata.*interface {}.
 74e R type.[1]interface {}
 6ff R type.[]interface {}
 69c R type.interface {}
     U type.string

所以目前的结论是:

当声明的包名称与包文件夹名称不同时,包声明将用作包的备用名称。

等价于this,但隐含:

import pkg2 "pkg1"

顺便说一句,由于包声明没有反映在编译的.a文件中,我猜golang编译需要.go文件的存在。

【问题讨论】:

  • 顺便说一句:将实用程序函数保存在文件utilities.go 中并仍在package main 下是完全可以的。 Go 中的包通常由多个文件组成,并且通常包含多种类型。

标签: go


【解决方案1】:

同一个包 AKA 文件夹中的 go 文件必须具有相同的包名。唯一的例外是可以具有 _test 扩展名的测试。规则是 1 个文件夹,1 个包,因此同一文件夹中的所有 go 文件的包名相同。

答案是肯定的,将“hello”包文件移动到自己的文件夹中,或者,对同一目录中的所有文件使用相同的包名。

【讨论】:

  • 你的意思是把“utilities.go”移到另一个文件夹吗?拥有一个只包含 main.go 文件的文件夹看起来很笨拙。
  • utilities.go 不是一个包,它是一个文件。重要的是文件中的包名,你不能在同一个文件夹中有一个“hello”和一个“main”包并构建你的代码,仅此而已,这不是意见,这就是 Go 的工作原理。跨度>
  • 我想我可以将package main 放入utilities.go 并仍然将其保存在与main.go 相同的文件夹中。 Go 仍然会通过名称 main 找到入口点。
  • 原来内置的cmd\cgo 包确实将package main 用于同一包文件夹中的所有*.go 文件。
  • 并没有真正改变您的问题。一个文件夹中只有一个包。我不管包的名字是什么。同一个文件夹中不能有 2 个包。
猜你喜欢
  • 2013-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-23
  • 2012-06-13
  • 2013-02-11
相关资源
最近更新 更多