如果package文件夹中存在多个文件且一个文件包含“ package main”,则如何指定软件包名称?

Suppose I have a package folder as below:

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

In the main.go, I have:

package main

In the utilities.go, I have:

package hello

I did this because:

  • I don't want to put all the utilities into the single main.go file.
  • And the utilities are only used by this package so I don't want to put it out of the hello folder.

But when I run go list hello, it gives me this:

can't load package: package hello: found packages main (main.go) and hello (utilities.go) in E:\Workbench\Go\src\hello

Then I remove the utilities.go and tried the go list hello again with only main.go. It gives me this:

hello

So do I have to move all the utilities to another package folder?

Do I have to keep only the single main.go in the hello package folder because it seems it doesn't get along well with other package names?

ADD 1

An useful ref: http://thenewstack.io/understanding-golang-packages/

ADD 2

After a few brief experiments, I guess the import yyy decides the link search path while the package xxx declaration decides the exported symbol name in the compiled .a file.

Because I noticed these facts:

  • The package xxx declaration doesn't have to be the same as the containing package folder name, say yyy.
  • But the import yyy declaration must use the package folder path yyy.
  • When using a symbol from a package, we must still use the xxx.Symbol rather than yyy.Symbol.

ADD 3

To confirm my guess in ADD 2, I did this:

(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".
}

The above 2 files can compile and run.

But if I changed to this:

(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?
}

This will give:

....\src\cmd1\main.go:3: imported and not used: "pkg1" as pkg2

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

And to double confirm, I checked the compiled pkg1.a file with go tool nm pkg1.a, I didn't see package name affects the exported symbols. (btw, the GNU nm tool seems not be able to recognize the golang .a file format.)

     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

So the conclusion so far is:

When the declared package name is different from the package folder name, package declaration will be used as an alternate name of the package.

Equivalent to this, but implicitly :

import pkg2 "pkg1"

And btw, since the package declaration is not reflected in the compiled .a file, I guess the golang compilation requires the presence of .go file.

go files in the same package AKA folder must have the same package name. The only exception are tests that can have a _test extension. The rule is 1 folder , 1 package therefore the same package name for all go files in the same folder.

The answer is yes , move the "hello" package files to their own folder or , use the same package name for all files in the same directory.