【问题标题】:How to import local packages in go?go中如何导入本地包?
【发布时间】:2016-05-30 13:39:45
【问题描述】:

我是新手,正在编写一个我想要本地化的示例代码。

在原来的main.go import 语句中是:

 import (
    "log"
    "net/http"
    "github.com/foo/bar/myapp/common"
    "github.com/foo/bar/myapp/routers"
)

现在我在/home/me/go/src/myapp 中有commonrouters

所以我将导入语句转换为:

import (
    "log"
    "net/http"
    "./common"
    "./routers"
)

但是当我运行 go install myapp 时,我得到了这些错误:

can't load package: /home/me/go/src/myapp/main.go:7:3: local import "./common" in non-local package

另外,当我在 import 语句中使用 commonrouters 而不是 ./common./routers 时,我得到:

myapp/main.go:7:3: cannot find package "common" in any of:
    /usr/local/go/src/common (from $GOROOT)
    /home/me/go/src/common (from $GOPATH)
myapp/main.go:8:2: cannot find package "routers" in any of:
    /usr/local/go/src/routers (from $GOROOT)
    /home/me/go/src/routers (from $GOPATH)

我该如何解决这个问题?

【问题讨论】:

  • 无论导入路径如何,所有导入都是“本地”的。详细解释见"How to Write Go Code"
  • @JimB 抛开哲学争论,我关心的是如何解决上述问题。
  • 我并不是要发表哲学声明,我是说所有导入都发生在您的本地文件系统中;无论它们是否来自远程仓库,都没有任何区别。不要尝试使用相对路径(它们有时会起作用,但不鼓励),并仔细阅读“如何编写 Go 代码”文档,特别是 "Code Organization" 上的部分。

标签: go


【解决方案1】:

好吧,我发现了问题所在。 基本上 Go 导入的起始路径是$HOME/go/src

所以我只需要在包名前面加上myapp,也就是import应该是:

import (
    "log"
    "net/http"
    "myapp/common"
    "myapp/routers"
)

【讨论】:

  • 使用myapp这样的项目名称是个坏主意,例如如果您更改项目名称,则所有导入都会失败
  • 有什么选择? Go 不建议您使用相对导入。
  • 当然,如果您更改项目名称,所有导入都会失败。项目名称很少更改。
  • 好吧,从 go1.11 开始,您可以使用新的模块系统。 go mod init <module_name> 然后只是 import "<module_name>/<pkg_name>"
  • 我们如何在.go文件中导入github.com/dgrijalva/jwt-go?我的 jwt-go 文件夹位于 src/github.com/dgrijalva
【解决方案2】:

如果您使用的是 Go 1.5 以上版本,您可以尝试使用 vendoring 功能。 它允许您将本地包放在 vendor 文件夹下,并以较短的路径导入它。 在您的情况下,您可以将 commonrouters 文件夹放在 vendor 文件夹中 所以它会像

myapp/
--vendor/
----common/
----routers/
------middleware/
--main.go

并像这样导入它

import (
    "common"
    "routers"
    "routers/middleware"
)

这会起作用,因为 Go 会尝试从项目的供应商目录(如果它至少有一个 .go 文件)而不是 $GOPATH/src 开始查找您的包。

仅供参考:您可以使用供应商做更多事情,因为此功能允许您将包的“所有依赖项的代码”放在您自己的项目目录中,这样它就能够始终为所有构建获得相同的依赖项版本。它就像 python 中的 npm 或 pip,但您需要手动将依赖项复制到您的项目中,或者如果您想让它变得简单,请尝试查看 Daniel Theophanes 的 govendor

有关此功能的更多信息,请尝试在此处查找

Understanding and Using Vendor Folder by Daniel Theophanes

Understanding Go Dependency Management by Lucas Fernandes da Costa

我希望你或其他人发现它有帮助

【讨论】:

  • 你的意思是 go lang 版本 1.15?
【解决方案3】:

您应该使用go mod init 创建您的包,例如go mod init github.com/my-org/my-package

例如,现在在my-package 中有一个名为utils 的子模块。

main.go
utils
 |- randstr.go

你的randstr.go 看起来像这样:

package utils

func RandStr(n int) string {
    // TODO: Generate random string....
    return "I am a random string"
}

然后在您的应用程序中的任何地方,您都可以像这样使用utils 包中的导出函数,例如main.go

package main

import (
    "fmt"

    // "github.com/my-org/my-package" is the module name at the
    // top of your `go.mod`
    "github.com/my-org/my-package/utils"
)

func main() {
    fmt.Printf("Random string: %s\n", utils.RandStr(20))
}

【讨论】:

  • 我发现你的答案很容易理解。一般来说,通过简单地复制模块目录中所需的文件并按照您的简单说明,可以消除任何版本控制系统的使用并且仍然能够使用 go 模块,这是否正确?我只是不喜欢将版本控制系统绑定到一种语言的开发系统并增加相关复杂性的概念,如果我可以通过简单地复制它们来维护所有代码,包括本地供应商编辑的代码。随着我对 Go 越来越有信心,我可能会集成使用带有版本控制的模块。
  • 对我来说效果很好。这应该是公认的答案
  • 谢谢,从 nodejs 迁移后,几乎一天都在尝试理解 go 中的导入/导出。迄今为止我找到的最简单的答案。
【解决方案4】:

导入路径与您的 $GOPATH$GOROOT 环境变量相关。例如,使用以下$GOPATH

GOPATH=/home/me/go

位于/home/me/go/src/lib/common/home/me/go/src/lib/routers 的包分别导入为:

import (
    "lib/common"
    "lib/routers"
)

【讨论】:

  • 是的,第一个例子是我的错误。
  • 工具不支持的相对路径是什么意思?
  • 你不能go install使用相对导入的包。
  • 我认为这是误解。我的意思是相对于 GOPATH。不仅仅是相对的,比如“../../mypackage”
  • 那是指您修复的关于相对于当前目录导入的部分。是的,所有用户导入都相对于$GOPATH/src
【解决方案5】:

一个例子:

  1. ./greetings,做go mod init example.com/greetings

  2. 从另一个模块,做go mod edit -replace=example.com/greetings=../greetings

  3. go get example.com/greetings

来自go tutorial

【讨论】:

    【解决方案6】:

    本地包在go中是个烦人的问题。

    对于我们公司的一些项目,我们决定根本不使用子包。

    • $ glide install
    • $ go get
    • $ go install

    所有工作。

    对于某些项目我们使用子包,并使用完整路径导入本地包:

    import "xxxx.gitlab.xx/xxgroup/xxproject/xxsubpackage

    但是如果我们 fork 这个项目,那么子包仍然引用原来的。

    【讨论】:

      【解决方案7】:

      关键是你如何在下面的命令中命名你的模块

      go mod init <TheNameGiven>
      

      然后引用内部文件夹中的模块,

      TheNameGiven/folder
      

      我在这里找到了最好的解决方案...Read More

      【讨论】:

        【解决方案8】:

        如题,文件夹结构为:

        /home/me/go/src/myapp
                        └─ common
                        └─ routers
        

        所以转到 myapp 目录

        cd /home/me/go/src/myapp
        

        go mod init myapp
        

        这将创建一个 go.mod 文件,让 Go 知道模块 myapp 的名称,这样当它查看任何包中的导入路径时,它不知道在别处寻找 myapp

        那么你可以在代码中做如下操作:

        import (
            "log"
            "net/http"
            "myapp/common"
            "myapp/routers"
        )
        

        现在包 common 和 routers 被导入。

        【讨论】:

          【解决方案9】:

          尝试使用 go mod init 命令更改包名。

          所以,我有 1.17,我有同样的导入问题。我的项目目录是 $GOPATH/src/myswagger/app-swagger-test。我将此命令运行到 app-swagger-test 目录:

          go mod init app-swagger-test
          go mod tidy
          

          在我的新 go.mod 文件中,包名是 app-swagger-test。例如,这个导入是错误的:

          import (
              ...
              "myswagger/app-swagger-test/internal/generated/restapi"
              "myswagger/app-swagger-test/internal/generated/restapi/operations"
          )
          

          所以我删除了 go.mod 和 go.sum。然后我将下一个命令运行到 app-swagger-test 目录:

          go mod init myswagger/app-swagger-test
          go mod tidy
          

          之后项目中的所有导入都成功导入。在新的 go.mod 文件中,第一行是:

          module myswagger/app-swagger-test
          

          也许这个信息很常见,但我没有找到。谢谢!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-09-02
            • 1970-01-01
            • 2019-10-06
            • 2021-06-17
            • 1970-01-01
            • 1970-01-01
            • 2019-12-26
            相关资源
            最近更新 更多