Go 的一个目录是否可以包含多个包

golang 同一个包下的文件可以分再目录放么

地址:https://segmentfault.com/q/1010000020626180/a-1020000020633068

标签:Go

详情描述

Go 语言中同一个包中的文件必须在同一个目录吗,有没有什么办法放呢?现在有一个包中有上百个文件放在一起,太乱了。

我的回答

可以再分目录放。

一个目录一般情况下只能是一个包,但目录下可以有子目录,而每个子目录都可以是一个包。

一个目录下只能一个包一般是正确的,但有个特殊情况,如果源码文件中包含了测试,测试的包名可以与主包名不同。

还有,Go 中有模块管理机制,一个模块可以由很多个包组成,即一个目录的下级目录都属于这个模块。

补充:我突然觉得,你问题里的包,从某种意义上,想表达的是一个模块,简单而言,就是 git clone 下来的内容不要理解为一个包,而要理解为一个模块。

一个简单例子。

有个目录是 github.com/poloxue/p1,假设包名为 p1。而 p1 下面还有个子目录 p2,即 github.com/poloxue/p1/p2,包名为 p2。两个不同目录下是不同的包。

如果希望 p1 目录下有两个包,可以创建一个测试文件 p1_test.go, 声明它的包名为 p1_test。

如果 github.com/poloxue/p1 目录下通过 go mod 创建了一个模块 github.com/poloxue/p1,那这里的 p1 和 p2 都属于 github.com/poloxue/p1 这个模块。


补充一个相关的问答。

Go 中同一个目录包含两个包是否有意义

地址:https://stackoverflow.com/questions/20427890/does-it-make-sense-to-have-two-packages-in-the-same-directory

标签:Go

详情描述

我有个项目,一个库,它导出了一些函数,同时还要提供了命令行执行,即必须有一个可执行文件。

目录结构的示例如下:

whatever.io/
    myproject/
        main.go
        myproject.go

可执行文件函数入口必须是 main package 中的 main 函数,这是 Go 编译器的要求。同时还要求 myproject 文件,即 myproject 包中函数可被其他地方使用。

当我尝试编译时,提示如下:

main.go:5:2: found packages myproject (myproject.go) and main (main.go) in $GOPATH/src/whatever.io/myproject

于是,我发现这是不行的。

我需要把函数库或者可执行命令的源码移到其他另外的包中。

优秀回答

Larry Battle 的回答

只需要把你的 myproject 包移到一个子目录下(与 main.go 同级)即可。要记住的是,新包的导入路径要相对 GOPATH。

一个例子:

user@user:~/p/go/test/so-multipack$ ls -R
.:
a  main.go

./a:
a.go
user@user:~/p/go/test/so-multipack$ cat main.go 
package main

import (
    "../so-multipack/a"
)
func main(){
    a.Hello()
}
user@user:~/p/go/test/so-multipack$ cat a/a.go 
package a
import (
    "fmt"
)
func Hello(){
    fmt.Println("hello from a")
}
user@user:~/p/go/test/so-multipack$ go run main.go 
hello from a
user@user:~/p/go/test/so-multipack$ go build 
user@user:~/p/go/test/so-multipack$ ls
a  main.go  so-multipack

Akavall 的回答

在一个目录下不能包含两个包,故而这里报错了。正如 Larry Battle 所言,把 myproject.go 移到一个新的文件下。

摘自 How to write go code

Go code must be kept inside a workspace. A workspace is a directory hierarchy with three directories at its root:

src contains Go source files organized into packages (one package per directory),

pkg contains package objects, and

bin contains executable commands.

翻译如下:

Go 代码必须在一个工作区中。一个工作区是一个层级的目录,在底层包含了三个目录。

src 包源码文件,一个包一个目录

pkg 包的编译生成的库文件。

bin 可执行文件

byxor 的回答

多数情况,的确只能是一个目录包含一个包。但有一例外,那就是 unittest。

案例:

两个不同的包(mypackage 和 mypackage_test)在一个目录中,成功编译。

目录结构如下:

mypackage/
  foo.go
  foo_test.go

mypackage/foo.go

package mypackage

func Add(a int, b int) int {
    return a + b
}

mypackage/foo_test.go:

package mypackage_test

...

规则

其一,两个包名要满足下面的规则。

  • 目录名称
  • 目录名称_test

其二,包 _test 的文件名要以 _test.go 结尾。

如果,编译器报错,比如 found packages "foo" and "bar",说明你违反了其中的某个规则。