In Go does the package name have to be identical to inner-most directory name?
Asked Answered
M

4

9

ATTENTION this question is about Go language specs not best practice or recommendation.

I have read many articles of packages but I still don't quite understand the relationship of directory and package name. Here is my example.

My project structure is like the following screenshots. When I do go run ~/go/src/myproj/main.go the error says:

src\myproj\main.go:5:2: cannot find package "myproj/pa/pb" in any of: c:\go\src\myproj\pa\pb (from $GOROOT) C:\Users\terry\go\src\myproj\pa\pb (from $GOPATH)

enter image description here

enter image description here

However if I change package pb to package pa in p.go, and change the import from "myproj/pa/pb" to "myproj/pa", and change fmt.Print(pb.Greet) to fmt.Print(pa.Greet) in main.go, it will work. Does the inner most directory must match the package declaration name? My go version is 1.14.4

Misprision answered 30/6, 2020 at 8:39 Comment(1)
"Does the inner most directory must match the package declaration name?" No, of course not. But this is a very sensible convention and you should never break it because people will hate you (rightfully) if you do.Pyrogallol
M
7

After some trials and errors I found out what happened. Package name has to be identical to inner-most directory name? No.

In main.go just do the following it should work.

package main

import (
    "fmt"
    "myproj/pa"
)

func main() {
    fmt.Print(pb.Greet)
}

Also we can give it an alias such as the following also works.

package main

import (
    "fmt"
    pc "myproj/pa"
)

func main() {
    fmt.Print(pc.Greet)
}

So it means, package in go is a directory of files with package xxx declaration. The directory name matters during the import. The directory is part of the path for the import. But what is used in the imported file is the xxx in package xxx or the alias for that xxx.

Of course, doing such kind of thing is not recommended, still the best practice is not to do this to confuse people.

Misprision answered 30/6, 2020 at 9:48 Comment(3)
Technical it is possible... But never ever should you do that.Ecumenicist
this question is asking Go specs not recommendation or best practice. by giving the above example, people will understand how go package works and not confused any more when see some 3rd package has such kind of thing.Misprision
I know what you want to say and I appreciate that you want to find out the technical details. The thing I am trying to say is that never ever in the 5 years I am working now with Go have I seen packages names differently than their source directory.Ecumenicist
E
6

In go, a convention is that a package's name should be equal to the name of its source directory.

Here is for example an excerpt from the Effective Go Blog:

Another convention is that the package name is the base name of its source directory; the package in src/encoding/base64 is imported as "encoding/base64" but has name base64, not encoding_base64 and not encodingBase64.

This has the effect that a single directory contains exactly one package. It is so fundamental in go that you can consider it a fixed rule, although technically, it is only a convention.

Ecumenicist answered 30/6, 2020 at 8:59 Comment(0)
F
6

In Go does package name has to be identical to inner-most directory name?

It doesn't have to be identical, but it is a common convention. You shouldn't deviate from it unless you have good reason to.

If you want to have a different package name and directory name, you can use the import comment with files's package clause.

package <package_name> // import "<import_path>"

This is useful your file structure isn't conducive to a descriptive name, for example if using multiple versions in a filepath.

For example, Google's client SDK uses paths like the following:

  • Package Name: slides
  • Import Path: google.golang.org/api/slides/v1

To support this, the file's package clause is as follows:

package slides // import "google.golang.org/api/slides/v1"

This way, the following can be done in the calling code, which looks sensible.

package main

import(
    "google.golang.org/api/slides/v1"
)

func main() {
    fmt.Println(slides.PresentationsScope)
}

See more here: https://github.com/googleapis/google-api-go-client/blob/master/slides/v1/slides-gen.go

In the example here, you would use:

package pb // import "myproj/pa"

If you do not use the package clause approach, editors may automatically add an alias to your code, e.g.:

import pb "myprog/pa"
Frown answered 1/7, 2020 at 8:20 Comment(0)
M
1

The package name does not have to be the base of the package directory. The go tool goimports, when cleaning up the imports of a source file, will in fact take the package name and show it as an alias for the import if it doesn't match the base - to make the import code look to make more sense but the alias isn't necessary - the file will compile without it. When looking at a package's AST, the *types.Package has a Name method which returns the package name. When loading packages with the golang.org/x/tools/go/packages.Load function, the *packages.Package returned has a Name property which also returns the package name. This can be quite useful when generating code by program.

Masurium answered 21/9, 2021 at 3:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.