How do packages work in golang

huangapple go评论65阅读模式
英文:

How do packages work in golang

问题

我正在尝试更好地理解Go语言中的包(package)工作原理,特别是关于Go语言实际强制执行的内容,而不是通常做法或被认为是良好实践的内容(我们可以稍后讨论良好实践,但我希望先理解Go语言)。

根据《Effective Go》中的描述:

> "另一个约定是包名是其源代码目录的基本名称..."

然而,上述描述似乎并不是Go语言强制执行或要求的。因此,我想知道是否允许在同一个目录下有多个具有不同包声明的文件。如果允许在同一个目录中有多个包声明,那么如何导入它们并在同一个文件中分别使用它们?基本上,我猜我遇到的问题之一是由于一些Go教程/文档的措辞问题。如果这只是一种约定,那么对我来说,这意味着它不是语言强制执行的。因为例如,Go程序员不会按照约定为函数写关键字func。我们写func是因为否则Go会报错,代码将无法编译。因此,我希望通过下面的示例来澄清这个问题(如果可能的话,还可以更改Go的文档,因为在我看来,这是一个重要问题,应该解决)。

例如,假设我有三个文件A.goB.goC.go,它们分别打印一个打印函数Print(),分别打印a、b、c。它们都在同一个名为base的基本目录中。然后,每个文件都有一个不同的包声明package Apkgpackage Bpkgpackage Cpkg

那么你如何导入它们呢?下面的代码是否可行?

package main

import(
    nameA "github.com/user_me/base/Apkg"
    nameB "github.com/user_me/base/Bpkg"
    nameC "github.com/user_me/base/Cpkg"
)

func main() {
    nameA.Print() //打印a
    nameB.Print() //打印b
    nameC.Print() //打印c
}

或者,如果包声明的名称已经不同,我们甚至不需要指定名称:

package main

import(
    "github.com/user_me/base"
)

func main() {
    Apkg.Print() //打印a
    Bpkg.Print() //打印b
    Cpkg.Print() //打印c
}

打印的文件分别是:

A.go:

//位于github.com.user_me/base目录下的文件,文件名为A.go
package Apkg

import "fmt"

func Print(){
    fmt.Println("A")
}

B.go:

//位于github.com.user_me/base目录下的文件,文件名为B.go
package Bpkg

import "fmt"

func Print(){
    fmt.Println("B")
}

C.go:
//位于github.com.user_me/base目录下的文件,文件名为C.go
package Cpkg

import "fmt"

func Print(){
    fmt.Println("C")
}

另外,如果包名与base不同,有人能否向我解释一下实际的导入方式是怎样的?如果包名是package Apkg,在base中导入的方式是import github.com/user_me/base还是import github.com/user_me/base/Apkg还是github.com/user_me/Apkg

我还没有测试过这个,但我很快就会测试。对于我来说,Go语言中的导入问题有点令人困惑,我希望能得到一个答案并与世界分享。

英文:

I was trying to understand how packages work in go better in terms of what golang actually enforces rather than what is usually done or considered good practice (we can talk about good practice later too, but I wish to understand go first).

From effective go it says:

> "Another convention is that the package name is the base name of its source directory..."

However, the description above doesn't seem to be forced by go or required. Thus, I was wondering, if I was allowed to have multiple files with different package declarations at the top in the same directory base. If I am allowed to have multiple package declaration in the same directory, how do I then import them and use each one separately in the same file? Basically, I guess one of the problem I have is due to the wording of some of the go tutorial/documentation. If it is by convention, then for me, its implied that it is NOT enforced by the language. Because for example, go programmers do NOT write the keyword func for a function by convention. We write func because otherwise go will yell at you and it will not compile. Thus, I wish to clarify this with the example bellow (and if possible change the documentation for go, because this is a big deal in my opinion, how can this be done?).

For example say I have three file A.go, B.go, C.go that print a print function Print() that simply prints a,b,c respectively. They are all on the same base directory called maybe base. Then each has a different package declaration package Apkg, package Bpkg, package Cpkg.

how would you then go and import them? Would something as follow work?

package main

import(
    nameA "github.com/user_me/base/Apkg"
    nameB "github.com/user_me/base/Bpkg"
    nameC "github.com/user_me/base/Cpkg"
)

func main() {
    nameA.Print() \\prints a
    nameB.Print() \\prints b
    nameC.Print() \\prints c
}

or maybe we don't even need to specify the name if the package statments are the top are already different:

package main

import(
    "github.com/user_me/base"
)

func main() {
    Apkg.Print() \\prints a
    Bpkg.Print() \\prints b
    Cpkg.Print() \\prints c
}

the printing file are:

A.go:

//file at github.com.user_me/base and name A.go
package Apkg

import "fmt"

func Print(){
    fmt.Println("A")
}

B.go:

//file at github.com.user_me/base and name B.go
package Bpkg

import "fmt"

func Print(){
    fmt.Println("B")
}

C.go:
//file at github.com.user_me/base and name C.go
package Cpkg

import "fmt"

func Print(){
    fmt.Println("C")
}

Also, if you can have a name different from the base, could someone clarify to me how the import is actually done? If the package name is package Apkg in base does the import have to be import github.com/user_me/base or import github.com/user_me/base/Apkg or github.com/user_me/Apkg.

I have not yet tested this but I will do so soon. The importing deal in go has been a little confusing for me and would love to get an answer and share it with the world.

答案1

得分: 9

不,每个文件夹只能有一个包,所以你需要按照以下方式组织文件:

$GOPATH/src/github.com/user_me/base/Apkg/a.go
$GOPATH/src/github.com/user_me/base/Bpkg/b.go
$GOPATH/src/github.com/user_me/base/Cpkg/c.go

否则,你将无法构建它:

┌─ oneofone@Oa [/t/blah]                                                                                                         
└──➜ go build
can't load package: package .: found packages pkgA (blah1.go) and pkgB (blah2.go) in /tmp/blah

你的包名不需要与它们所在的目录同名,但是同一目录中的所有文件必须具有相同的包名。

此外,你可以在导入时重命名包,例如:

import (
   cr "crypto/rand"
   mr "math/rand"
)

或者你的库被称为main(不好的主意):

import m "github.com/user_me/base/main"
英文:

No, it's 1 package per folder, so you would have to have them :

$GOPATH/src/github.com/user_me/base/Apkg/a.go
$GOPATH/src/github.com/user_me/base/Bpkg/b.go
$GOPATH/src/github.com/user_me/base/Cpkg/c.go

You can't even build it otherwise:

┌─ oneofone@Oa [/t/blah]                                                                                                         
└──➜ go build
can't load package: package .: found packages pkgA (blah1.go) and pkgB (blah2.go) in /tmp/blah

Your your package name doesn't need to have the same name as the directory they are in, however all files in one directory must have the same package name.

Also, you can rename packages on import, for example:

import (
   cr "crypto/rand"
   mr "math/rand"
)

Or your library is called main (bad idea btw) :

import m "github.com/user_me/base/main"

huangapple
  • 本文由 发表于 2014年6月21日 03:53:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/24334677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定