如何在Go中导入本地包?

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

How to import local packages in go?

问题

我是你的中文翻译助手,以下是翻译好的内容:

我刚开始学习Go,并且正在处理一个我想要本地化的示例代码。

在原始的 main.go 文件中,导入语句如下:

 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

另外,当我在导入语句中使用 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)

我该如何解决这个问题?

英文:

I am new to go and working on an example code that I want to localize.

In the original main.go import statement it was:

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

Now I have common and routers package in /home/me/go/src/myapp

So I converted the import statement to:

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

But when I run go install myapp I get these errors:

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

Also, when I use common and routers instead of ./common and ./routers in the import statement, I get:

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 can I fix this?

答案1

得分: 139

嗯,我找到了问题所在。
基本上,Go语言的导入路径起始位置是$HOME/go/src

所以我只需要在包名前面添加myapp,也就是导入应该是这样的:

import (
    "log"
    "net/http"
    "myapp/common"
    "myapp/routers"
)
英文:

Well, I figured out the problem.
Basically Go starting path for import is $HOME/go/src

So I just needed to add myapp in front of the package names, that is, the import should be:

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

答案2

得分: 73

你应该使用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: 生成随机字符串....
	return "我是一个随机字符串"
}

然后,在你的项目的任何地方,你可以像这样使用utils包中的导出函数,例如在main.go中:

package main

import (
	"fmt"

    // "github.com/my-org/my-package" 是你的`go.mod`文件顶部的模块名
	"github.com/my-org/my-package/utils"
)

func main() {
	fmt.Printf("随机字符串:%s\n", utils.RandStr(20))
}
英文:

You should have created your package with go mod init e.g. go mod init github.com/my-org/my-package

Now in my-package you have a sub module called utils for example.

main.go
utils
 |- randstr.go

And your randstr.go looks like this:

package utils

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

And then anywhere in your project you would use exported (capitalized) functions from the utils package like this, for example in 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))
}

答案3

得分: 62

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

在您的情况下,您可以将commonrouters文件夹放在vendor文件夹内,就像这样:

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

然后像这样导入它们:

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

这样可以正常工作,因为Go会从您的项目的vendor目录开始查找您的包(如果它至少有一个.go文件),而不是$GOPATH/src。

顺便说一下:您可以在vendor中做更多的事情,因为这个功能允许您将“所有依赖包的代码”放在您自己项目的目录中,这样它将始终能够获取相同版本的依赖项。这有点像Python中的npm或pip,但您需要手动将依赖项复制到您的项目中,或者如果您想简化操作,可以尝试使用Daniel Theophanes的govendor工具。

要了解更多关于这个功能的信息,请参考以下链接:

Daniel Theophanes的《理解和使用Vendor文件夹》

Lucas Fernandes da Costa的《理解Go依赖管理》

希望对您或其他人有所帮助。

英文:

If you are using Go 1.5 above, you can try to use vendoring feature.
It allows you to put your local package under vendor folder and import it with shorter path.
In your case, you can put your common and routers folder inside vendor folder
so it would be like

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

and import it like this

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

This will work because Go will try to lookup your package starting at your project’s vendor directory (if it has at least one .go file) instead of $GOPATH/src.

FYI: You can do more with vendor, because this feature allows you to put "all your dependency’s code" for a package inside your own project's directory so it will be able to always get the same dependencies versions for all builds. It's like npm or pip in python, but you need to manually copy your dependencies to you project, or if you want to make it easy, try to look govendor by Daniel Theophanes

For more learning about this feature, try to look up here

Understanding and Using Vendor Folder by Daniel Theophanes

Understanding Go Dependency Management by Lucas Fernandes da Costa

I hope you or someone else find it helpfully

答案4

得分: 25

导入路径是相对于您的$GOPATH$GOROOT环境变量的。例如,假设您的$GOPATH如下所示:

GOPATH=/home/me/go

位于/home/me/go/src/lib/common/home/me/go/src/lib/routers的包可以分别这样导入:

import (
    "lib/common"
    "lib/routers"
)
英文:

Import paths are relative to your $GOPATH and $GOROOT environment variables. For example, with the following $GOPATH:

GOPATH=/home/me/go

Packages located in /home/me/go/src/lib/common and /home/me/go/src/lib/routers are imported respectively as:

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

答案5

得分: 13

一个例子:

  1. ./greetings目录下,执行go mod init example.com/greetings

  2. 在另一个模块中,执行go mod edit -replace=example.com/greetings=../greetings

  3. 执行go get example.com/greetings

来自Go教程

英文:

an example:

  1. in ./greetings, do go mod init example.com/greetings

  2. from another module, do go mod edit -replace=example.com/greetings=../greetings

  3. go get example.com/greetings

from the go tutorial

答案6

得分: 9

请按照这里的说明进行操作:https://go.dev/doc/tutorial/call-module-code

主要是需要在你的 go.mod 文件中进行替换调用。

module example.com/hello

go 1.16

replace example.com/greetings => ../greetings
英文:

Follow instructions here https://go.dev/doc/tutorial/call-module-code

Mainly you need the replace call in your go.mod file.

module example.com/hello

go 1.16

replace example.com/greetings => ../greetings

答案7

得分: 8

本地包是Go语言中的一个令人讨厌的问题。

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

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

这些命令都可以正常工作。

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

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

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

英文:

Local package is a annoying problem in go.

For some projects in our company we decide not use sub packages at all.

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

All work.

For some projects we use sub packages, and import local packages with full path:

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

But if we fork this project, then the subpackages still refer the original one.

答案8

得分: 5

根据问题中的描述,文件夹结构如下:

/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 包。

英文:

As in the question, the folder structure is:

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

So go to myapp dir

cd /home/me/go/src/myapp

Do

go mod init myapp

This will create a go.mod file which lets Go know the name of the module myapp so that when it’s looking at import paths in any package, it knows not to look elsewhere for myapp

Then you can do the following in the code:

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

Now package common and routers gets imported.

答案9

得分: 5

另一种方法是使用 go1.18 之后的 go.work 文件。

首先,本地的 common 包必须是一个模块,所以在 common 文件夹内提供一个 go.mod 文件:

module common

go 1.18

现在你可以手动在根目录创建一个 go.work 文件,或者调用 go work init,然后依次调用 go work use .go work use ./common。文件内容如下:

go 1.18

use (
	.
	./common
)

最后,你可以通过包名在代码中导入该包:

package main

import "common"

只需记住不要提交你的 go.work 文件 如何在Go中导入本地包?

英文:

Another approach, available since go1.18, is to use a go.work file.

First, the local common package has to be a module, so provide a go.mod file inside the common folder:

module common

go 1.18

You can now create a go.work file in the root of your directory manually or call go work init, then go work use . and finally go work use ./common. It will look like this:

go 1.18

use (
	.
	./common
)

Finally you can import the package in your code by name

package main

import "common"

Just remember to not commit your go.work files 如何在Go中导入本地包?

答案10

得分: 3

关键是你在以下命令中给模块命名的方式:

go mod init <TheNameGiven>

然后在内部文件夹中引用模块,使用以下方式:

TheNameGiven/folder

我在这里找到了最佳解决方案... 阅读更多

英文:

The key is how you name your module in the following command

go mod init &lt;TheNameGiven&gt;

Then refer the modules in the inner folder with,

TheNameGiven/folder

I have found the best solution here... Read More

答案11

得分: 2

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

所以,我有go 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

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

英文:

Try to change the package name with the go mod init command.

So, I have go 1.17, and I have the same import problem. My project directory is $GOPATH/src/myswagger/app-swagger-test. I ran this command into app-swagger-test dir:

go mod init app-swagger-test
go mod tidy

In my new go.mod file the package name is app-swagger-test. For example, this import was wrong:

import (
    ...
	&quot;myswagger/app-swagger-test/internal/generated/restapi&quot;
	&quot;myswagger/app-swagger-test/internal/generated/restapi/operations&quot;
)

So I removed go.mod and go.sum. And I ran next commands into app-swagger-test dir:

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

After that all imports in the project were imported successfully. In the new go.mod file the first line is:

module myswagger/app-swagger-test

Maybe this information is common, but I did not find it. Thanks!

答案12

得分: 0

最小项目结构:

.
├── go.mod
├── main.go
└── utils
    └── myUtil.go

main.go:

package main

import "main/utils"

func main() {
	utils.DoSomething()
}

utils/myUtil.go:

package utils

func DoSomething() {
	// 在这里做一些事情
}

go.mod:

module main

go 1.20
英文:

Minimal project structure:

.
├── go.mod
├── main.go
└── utils
    └── myUtil.go

main.go:

package main

import &quot;main/utils&quot;

func main() {
	utils.DoSomething()
}

utils/myUtil.go:

package utils

func DoSomething() {
	// do something here
}

go.mod:

module main

go 1.20

huangapple
  • 本文由 发表于 2016年2月18日 19:47:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/35480623.html
匿名

发表评论

匿名网友

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

确定