Golang中如何调用另一个包里的函数
Golang中如何调用另一个包里的函数 这个问题之前已经被问过很多次了,但我只想知道为什么它不起作用的解释。
src
|—main
|–mail – main.go
|–main.go
我想在 mail/main.go 中调用 main.go 里的函数
这个可以工作。为什么?:
import (
mail "./mail"
"fmt"
)
但为什么这个不行?
import (
"main/mail"
"fmt"
)
在任何路径中都找不到包 “main/mail”: /usr/local/go/src/main/mail (来自 $GOROOT) /Users/sibert/go/src/main/mail (来自 $GOPATH)
据我所知路径是正确的。
我寻求的是对其工作原理的解释,而不是解决方案。
更多关于Golang中如何调用另一个包里的函数的实战教程也可以访问 https://www.itying.com/category-94-b0.html
Jaytn:
恐怕我无法回答你的问题,因为据我所知它不应该这样运作
如果不使用Github,应该如何操作?
更多关于Golang中如何调用另一个包里的函数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
或许你应该使用来自 http://github.com 的路径
我目前还没有使用 GitHub。所以我在本地有这些 go 文件…
在$GOPATH/src中不允许使用相对导入,您说它可以正常工作,这意味着您可能没有使用Go工作区?请问安装的Go版本是什么?
由于某些原因,这个方法不起作用。
import (
"mymodule/mail")
但这个方法可以
import (
"../mail")
有人能给我解释一下吗?
或许你应该使用来自 http://github.com 的路径
例如:导入 “github.com/web/mail”
在 http://github.com 创建你的用户名文件夹,并将你的项目放在该文件夹中,这样能获得更好的文件夹结构。
我进行了一些调查,你的情况似乎有些奇怪…
能否分享你的项目结构、go env的输出结果以及你的.go文件的开头部分?
凭直觉判断,我认为可能是你的Go工作区设置有问题,比如你提到的"src"文件夹实际上不在你的GOPATH中。这至少可以解释目前为止的所有错误信息。
func main() {
fmt.Println("hello world")
}
codekid:
Go 无法找到你项目文件夹中的 mail 包, 尝试导入
项目名/mail而不是main/mail。(将 项目名 替换为包含 main.go 的文件夹名称)
如果我理解正确的话,文件夹结构应该是这样的?

使用这个
import (
"fmt"
"web/mail"
)
执行 go build 时出现以下错误:
在任何路径中都找不到包 “web/mail”: /usr/local/go/src/web/mail (来自 $GOROOT) /Users/sibert/go/src/web/mail (来自 $GOPATH)
我哪里做错了?
据我所知,情况完全如你所述(或你在第一篇帖子中描述的那样)。 另外,我推荐阅读这篇文章。
我的意思是,我不明白为什么在你描述的情况下事情会这样运行或不运行,因为它们本不应该有这样的表现(应该是相反的情况)。所以你的环境中正在发生一些我无法识别的异常情况。
关于"不使用Github时"的情况:可能无需在意。
无论你的项目位于src/github.com/yourname/yourproject还是src/yourproject,这(对你的用例来说)完全无关紧要。
你会发现有些人建议将项目放在src/github.com/yourname/目录下,即使你只是在本地开发,但他们通常假设你将来可能会上传代码;那样你就需要修改其他项目中的所有导入语句。但如果这不适用于你,你可以放心忽略这个建议(除非我遗漏了什么)。
这会导致循环依赖问题,这是不被允许的。
调用函数的解决方法是减少与入口包(即 main)的耦合。
例如,您可以将函数移至 mail.go:
mail/mail.go
package mail
func SomeFunc() {
fmt.Println("I'm doing something")
}
在 main.go 中,您可以这样调用:
package main
import "mymodule/mail"
func main() {
mail.SomeFunc()
}
这是完全可行的。
关于这部分错误信息:
无法在任何路径中找到包 “main/mail”: /usr/local/go/src/main/mail(来自 $GOROOT) /Users/sibert/go/src/main/mail(来自 $GOPATH)
Go 无法找到您项目文件夹中的 mail 包,
请尝试导入 projectName/mail 而不是 mail 或 main/mail。(将 projectName 替换为包含 main.go 的文件夹名称)
感谢。 恐怕我无法回答您的问题,因为据我所知它不应该这样工作,而且我无法复现您的结果。
您说得对,导入路径应该是某些Go工作区中的绝对唯一标识符。
例如 import some/thing 会在所有 $GOPATH/src/some/thing 中查找
这里的"绝对"指的是非相对路径,这就是为什么您要导入 main/mail 而不仅仅是 mail(或者 ./mail),即使它是当前包的子包。
您可以使用相对路径进行导入,但据我所知,这仅适用于不在Go工作区中的项目。如果您在工作区中使用相对路径,会抛出错误 local import "./mail" in non-local package。(参见此处)
这就是为什么我猜测您的文件不在GOPATH中,那么Go将无法找到它(因此出现 cannot find package 错误),但会允许使用相对路径(不会出现 local import in non-local package 错误)。但从您提供的信息来看,一切似乎都没问题。
很抱歉我无法提供更多帮助。
//顺便提一下:
您可以在本地使用远程路径(例如 github.com),即使它们实际上并未托管在那里。它们的特殊之处仅在于告诉 go get 如何在本地不可用时获取它们。编译器不会关心所有这些,只会使用本地版本(如果不存在则失败)。但这对您的原始问题没有帮助。
Jaytn:
我做了一些调查,你的情况似乎有些奇怪… 你能分享一下你的项目结构、
go env的输出结果以及你的 .go 文件的开头部分吗?
go env
GOARCH=“amd64” GOBIN="" GOCACHE="/Users/sibert/Library/Caches/go-build" GOEXE="" GOHOSTARCH=“amd64” GOHOSTOS=“darwin” GOOS=“darwin” GOPATH="/Users/sibert/go" GORACE="" GOROOT="/usr/local/go" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64" GCCGO=“gccgo” CC=“clang” CXX=“clang++” CGO_ENABLED=“1” CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG=“pkg-config” GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/s5/8y4xhk5d5kq1rbd5r3mk4lzw0000gn/T/go-build619608189=/tmp/go-build -gno-record-gcc-switches -fno-common"
main:
package main
import (
"../mail"
"fmt"
"html/template"
"net/http"
"strings"
)
mail:
package mail
import (
"log"
"net/smtp"
)
这是一个关于Go模块导入路径的常见问题。关键在于Go模块系统如何解析包路径,以及相对导入与绝对导入的区别。
工作原理解释
相对导入(你的第一个示例)
import (
mail "./mail"
fmt "fmt"
)
这里使用相对路径 "./mail",Go编译器会在当前目录的相对路径中查找 mail 包。这种方式:
- 不依赖于
GOPATH或模块名称 - 直接基于文件系统路径解析
- 适用于简单的项目结构或没有配置模块的情况
绝对导入(你的第二个示例)
import (
"main/mail"
fmt "fmt"
)
这里使用绝对路径 "main/mail",Go会:
- 首先检查是否在Go模块中(有go.mod文件)
- 如果找到go.mod,使用模块名称作为前缀
- 如果没有go.mod,回退到
GOPATH模式
为什么第二个示例失败
在你的情况下,"main/mail" 失败是因为:
-
没有go.mod文件:你的项目可能没有初始化Go模块,所以Go回退到
GOPATH模式 -
GOPATH模式下的路径解析:在
GOPATH模式下,Go期望包路径对应文件系统路径:- 期望在
$GOPATH/src/main/mail找到包 - 但你的项目在
src/main/mail而不是$GOPATH/src/main/mail
- 期望在
-
目录结构不匹配:你的实际目录结构是:
src/main/mail/main.go src/main/main.go但Go在
GOPATH模式下寻找的是:$GOPATH/src/main/mail/
验证示例
创建一个简单的测试来演示:
main.go:
package main
import "fmt"
func HelloFromMain() {
fmt.Println("Hello from main package")
}
mail/main.go:
package mail
import "fmt"
func SendEmail() {
fmt.Println("Sending email from mail package")
}
使用相对导入可以工作:
package main
import (
mail "./mail"
)
func main() {
mail.SendEmail()
}
但绝对导入 "main/mail" 在缺少go.mod或正确GOPATH设置时会失败。
根本原因是Go的包解析机制在模块模式和GOPATH模式下的不同行为,以及相对路径与绝对路径解析的逻辑差异。

