【发布时间】: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