Go中的相对进口

Go中的相对进口,go,Go,我有一个go项目,目录结构如下 utils(pkg) | auth.go (has a function names test1) controllers(pkg) | login.go (has a function names test2) 我正在尝试从login.go访问函数test1。这就是我所做的 import "../utils" func test2(c *gin.Context) bool{ utils.test1() } 但是我总是得到未解析的引用

我有一个go项目,目录结构如下

utils(pkg)
   | auth.go (has a function names test1)
controllers(pkg)
   | login.go (has a function names test2)
我正在尝试从login.go访问函数test1。这就是我所做的

import "../utils"

func test2(c *gin.Context) bool{
      utils.test1()
}

但是我总是得到
未解析的引用test1
。我是新来的。有人能帮我解释为什么我会出现这个错误吗?

不,Go中没有相对导入。
您应该使用绝对路径:

GOPATH环境变量指定工作区的位置。它可能是开发Go代码时需要设置的唯一环境变量。要开始,请创建一个工作区目录并相应地设置GOPATH。见:

导入路径 导入路径是唯一标识包的字符串。包的导入路径对应于其在工作区中的位置 或者在远程存储库中(解释如下)

标准库中的包具有较短的导入路径 例如“fmt”和“net/http”。对于您自己的软件包,您必须选择 基本路径不太可能与未来添加到 标准库或其他外部库

如果您将代码保存在某个源存储库中,那么应该使用该源存储库的根作为基本路径。对于 例如,如果您在GitHub.com/user上有一个GitHub帐户,那么 成为您的基本路径

请注意,您不需要将代码发布到远程存储库 在你建造它之前。组织代码只是一个好习惯 好像有一天你会出版它。实际上,你可以选择任何一种 任意路径名,只要它对标准库是唯一的 以及更大的围棋生态系统

示例:

本例假设您已在操作系统环境中设置了
GOPATH=/goworkdir

文件:
goworkdir/src/project1/utils/auth.go

package utils

func Test1() string {
    return "Test1"
}
package controllers

import "project1/utils"

func Test2() string {
    return utils.Test1()
}
package main

import (
    "fmt"
    "project1/controllers"
)

func main() {
    fmt.Println(controllers.Test2())
}
文件:
goworkdir/src/project1/controllers/login.go

package utils

func Test1() string {
    return "Test1"
}
package controllers

import "project1/utils"

func Test2() string {
    return utils.Test1()
}
package main

import (
    "fmt"
    "project1/controllers"
)

func main() {
    fmt.Println(controllers.Test2())
}
文件:
goworkdir/src/project1/main.go

package utils

func Test1() string {
    return "Test1"
}
package controllers

import "project1/utils"

func Test2() string {
    return utils.Test1()
}
package main

import (
    "fmt"
    "project1/controllers"
)

func main() {
    fmt.Println(controllers.Test2())
}
现在,如果您
go运行main.go
,您应该会看到输出:

Test1

我认为您可以在源文件旁边放置一个供应商目录,其作用类似于相对GOPATH,然后创建一个相对符号链接,该链接指向您要在供应商目录中导入的包,然后导入包,就好像供应商目录是您的$GOPATH/src/

这与go 1.11引入go模块后有所不同

因此,如果您切换到go模块,并且您的模块名为“m”,那么在项目树中进行相对导入的惯用方法是:在需要导入项目中这些包的位置使用:
import“m/utils”
import“m/controllers”
。 有关详细信息,请参阅:


GoLand用户-默认情况下,这些形式的导入在IDE中显示为错误。您需要在设置中启用Go模块集成


以下是另一个示例项目结构,其中包含正确导入所需的文件内容:

test1/
   utils/
      texts.go
   main.go
   go.mod
包括以下内容:

go.mod

module mycompany.com/mytest

go 1.15
utils/text.go
(要使函数从不同的包中可见,它需要以大写字母开头):

main.go
(只支持完整的导入名称,没有从同一模块导入的快捷方式):


给定此目录配置:

.
├── controllers
│   └── login.go
├── main.go
└── utils
    └── auth.go
文件main.go:

package main

import "./controllers"

func main() {
    controllers.Test2("Hello")
}
文件控制器/login.go:

package controllers

import "../utils"

func Test2(msg string) {
    utils.Test1(msg)
}
文件utils/auth.go:

package utils

import . "fmt"

func Test1(msg string) {
    Println(msg)
}
成果工程:

$ go build -o program main.go 
$ ./program 
Hello

所以你想做的事很管用。唯一的区别是我使用了大写函数名,因为导出符号是必需的。

你的意思是,如果我更改保存代码的存储库,那么我需要修改代码中的所有导入语句?这似乎不对。这个答案只是部分正确。如果使用GOPATH,那么实际的导入语句将采用以下形式:import“github.com/user/project1/utils”。这是因为go install与git存储库一起工作。按照答案中的建议,可以使用基于相对文件系统的路径,但是,这只能在本地工作,并且项目将无法与其他人共享。首先,感谢您指出此重要更新!一个小小的吹毛求疵:“在项目树中进行相对导入的惯用方法是[…]”——您描述的仍然是绝对导入,而不是相对导入。事实上,根据您链接到的常见问题中提到的GitHub问题,相对导入以前是可能的,但现在显然不再是了。我想这取决于如何定义“绝对”和“相对”。我的意思是“相对的”,在某种意义上说,它只存在于您当前的项目中。仅相对于当前项目模块名称存在。不在任何公开的Git回购中;不在系统的中央模块存储器中。在当前文件系统、代码库之外不可见。如果您的意思是“相对”,如“以文件系统方式使用.././like符号表示相对”,那么是的,您是对的。从这个意义上讲,这可能不符合“relative”的定义。relative的意思是不依赖外部名称或配置,例如“m”-这完全是基于相对目录结构而不是其他的。从这个意义上说,这不是相对的。它将是
“mycompany.com/mytest/test1/utils”
而不是
“mycompany.com/test1/utils”
,其余一切都是完美的。