Go:非本地包中的本地导入

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

Go: local import in non-local package

问题

我有以下的文件结构:

.
├── bin
│   └── hello
├── pkg
└── src
    └── jacob.uk.com
        ├── greeting
        │   └── greeting.go
        └── helloworld.go

5个目录,3个文件

使用以下的GOPATH:

/Users/clarkj84/Desktop/LearningGo

src文件夹中执行/usr/local/go/bin/go install jacob.uk.com后,我得到了错误信息local import "./greeting" in non-local package

helloworld.go文件内容如下:

package main;
import "./greeting"

func main() {
   
}
英文:

I have the following file structure:

.
├── bin
│   └── hello
├── pkg
└── src
    └── jacob.uk.com
        ├── greeting
        │   └── greeting.go
        └── helloworld.go

5 directories, 3 files

With the following GOPATH

/Users/clarkj84/Desktop/LearningGo

Upon executing /usr/local/go/bin/go install jacob.uk.com within the src folder, I get the error local import "./greeting" in non-local package

helloworld.go:

package main;
import "./greeting"

func main() {
   
}

答案1

得分: 46

你在使用go install命令指定非本地包时,不能使用本地导入。如果你想让本地导入起作用,首先要将工作目录更改为src/jacob.uk.com,然后执行go install命令(不指定包)。

当然,使用你提供的helloworld.go文件会得到一个编译错误:imported and not used。但是一旦你使用了导入的greeting包中的内容,它应该可以编译。

但是你不应该使用本地导入。相反,应该这样写:

import "jacob.uk.com/greeting"

这样做,你就可以在任何地方进行编译、运行和安装了。

英文:

You can't use local import when specifying a non-local package to go install. If you want the local import to work, first change working directory to src/jacob.uk.com then execute go install (without specifying the package).

Of course having the helloworld.go you provided you will get an compile error: imported and not used. But once you use something from the imported greeting package, it should compile.

But you shouldn't use local imports at all. Instead write:

import "jacob.uk.com/greeting"

And doing so you will be able to compile/run/install it from anywhere.

答案2

得分: 30

键入go build不能使用相对导入路径;您必须键入go build main.go

go install根本无法使用相对导入路径。

文档位于https://golang.org/cmd/go/#hdr-Relative_import_paths

请参阅

以获取解释。

英文:

Typing go build does not work with relative import paths; you must type go build main.go.

go install does not work at all with relative import paths.

It is documented at https://golang.org/cmd/go/#hdr-Relative_import_paths

See

for explanation.

答案3

得分: 16

你可以使用"go 1.11<="中的replace关键字来添加本地包。在你的go.mod文件中添加以下内容(不需要创建GitHub仓库,只需添加如下行):

module github.com/yourAccount/yourModule

go 1.15

require (
    github.com/cosmtrek/air v1.21.2 // indirect
    github.com/creack/pty v1.1.11 // indirect
    github.com/fatih/color v1.9.0 // indirect
    github.com/imdario/mergo v0.3.11 // indirect
    github.com/julienschmidt/httprouter v1.3.0
    github.com/mattn/go-colorable v0.1.7 // indirect
    github.com/pelletier/go-toml v1.8.0 // indirect
    go.uber.org/zap v1.15.0
    golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a // indirect
)

replace (
    github.com/yourAccount/yourModule/localFolder =&gt;"./yourModule/localFolder"
    github.com/yourAccount/yourModule/localFolder =&gt;"./yourModule/localFolder"
)

然后在你的main.go文件中导入:

import (
    alog "github.com/yourAccount/yourModule/localFolder"
    slog "github.com/yourAccount/yourModule/localFolder"
)
英文:

You can add the local packages using replace in go 1.11<=
go to your go.mod and use "replace" keyword, as below, (you do not need to create a github repo, just add the lines like this)

module github.com/yourAccount/yourModule

go 1.15

require (
	github.com/cosmtrek/air v1.21.2 // indirect
	github.com/creack/pty v1.1.11 // indirect
	github.com/fatih/color v1.9.0 // indirect
	github.com/imdario/mergo v0.3.11 // indirect
	github.com/julienschmidt/httprouter v1.3.0
	github.com/mattn/go-colorable v0.1.7 // indirect
	github.com/pelletier/go-toml v1.8.0 // indirect
	go.uber.org/zap v1.15.0
	golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a // indirect
)

replace (
	github.com/yourAccount/yourModule/localFolder =&gt;&quot;./yourModule/localFolder&quot;
	github.com/yourAccount/yourModule/localFolder =&gt;&quot;./yourModule/localFolder&quot;
)

Then in your main.go =>

import (
	alog &quot;github.com/yourAccount/yourModule/localFolder&quot;
	slog &quot;github.com/yourAccount/yourModule/localFolder&quot;
)

答案4

得分: 2

你可以使用供应商功能来绕过这个问题。
import "./greeting"改为import "greeting"
创建供应商目录mkdir vendor,并创建符号链接ln -s ../greeting vendor/greeting

英文:

you can bypass this using the vendor feature
change import &quot;./greeting&quot; to import &quot;greeting&quot;
create the vendor directory mkdir vendor and create a symlink ln -s ../greeting vendor/greeting

答案5

得分: 2

模块的名称必须是唯一的字符串。我认为这就是为什么我们经常使用域名作为模块名称的原因。

在这个模块中,名称非常独特,我尝试使用我本地的包名称,如下所示:

import "very-unique/packagename"

然后(显然),我有一个文件(在我的情况下是packagename.go),文件顶部有这行代码:

package packagename

但是它不起作用!当我创建一个名为packagename的目录,并将文件移动到该目录中时,它最终起作用了。

我个人更喜欢这个解决方案,而不是使用replace。通常,我认为当我们尝试在本地使用现有库的副本(使用路径)时,我们应该使用replace

英文:

Name of module has to be a unique string. I think that's why we use a domain name for a module name a lot.

// go.mod
module very-unique

go 1.17

In that module name is very unique, I tried package name I have locally like follows.

import &quot;very-unique/packagename&quot;

And (obviously) I had a file (it was packagename.go in my case) with this line on top.

package packagename

But it didn't work! It finally worked when I made a directory named packagename and moved the file into that directory.

I personally like this solution than using replace. Usually I think we should use replace when we try a copy of existing library locally (with a path).

答案6

得分: 0

可能有几个问题出错了。我将提供以下设置。

检查 GOPATH 环境变量

GOPATH 变量定义了你的工作空间。你可以通过输入 "go env" 来轻松地确定当前值。

如果你在 Windows 下安装 Go,GOPATH 环境变量会在安装过程中自动设置。然而:默认路径可能不是你首选的路径。你可以将该变量安全地设置为你希望的目标目录。

在 Windows 中更改环境变量,请参考这里:https://www.architectryan.com/2018/08/31/how-to-change-environment-variables-on-windows-10/

检查工作空间布局

如果你已经决定了工作空间的位置并设置了 GOPATH 环境变量,你应该在工作空间内创建三个文件夹:

src、pkg、bin

文件夹 "src" 是你的源代码所在的地方。"pkg" 包含外部导入的包。"bin" 包含编译后的源代码。

示例项目

工作空间的布局如下:

<workspace directory>
--> src
    --> oopexpertutil
        --> x.go
    --> y.go
--> pkg
    --> ...
--> bin
    --> ...

文件 "x.go"

package oopexpertutil

func checkMe(e error) {
    if e != nil {
        panic(e)
    }
}

文件 "y.go"

package main

import (
    "fmt"
    "io/ioutil"
    "oopexpertutil"
)

func main() {

    var data string = "Hello World!"
    var dataAsBytes = []byte(data)

    fmt.Println(data)

    err := ioutil.WriteFile("hello_world.txt", dataAsBytes, 0644)

    fmt.Println(err)

    oopexpertutil.checkMe(err)

}

失望...

这个设置仍然不起作用。你可能已经尝试了所有其他关于工作空间、包布局或 "go modules" 的答案。使其工作的最后一点要考虑的是:

将被引用包中的 "checkMe" 函数的名称更改为 "CheckMe",并更新使用方式...

Go 通过首字母的大小写来区分包中的导出函数和非导出函数,有一些约定。

英文:

There may several thing going wrong. I will provide following setup.

Check your GOPATH environment variable

The GOPATH variable defines your workspace. You can easily identify the current value if you type "go env".

If you install Go under Windows the GOPATH environment variable is set up automatically during installation process. Nevertheless: It could be that this default path is not your preferred choice. You may safely set this variable to a target directory to your wish.

To change environment variables in Windows look here: https://www.architectryan.com/2018/08/31/how-to-change-environment-variables-on-windows-10/

Check Workspace Layout

If you have decided where your workspace should reside and set up the GOPATH environemnt variable you should create three folders within the workspace:

src, pkg, bin

The folder "src" is the on where your source code reside. "pkg" includes external imports. "bin" contains the compiled sources.

Example Project

Layout within your workspace:

&lt;workspace directory&gt;
--&gt; src
    --&gt; oopexpertutil
        --&gt; x.go
    --&gt; y.go
--&gt; pkg
    --&gt; ...
--&gt; bin
    --&gt; ...

File "x.go"

package oopexpertutil

func checkMe(e error) {
    if e != nil {
        panic(e)
    }
}

File "y.go"

package main

import (
	&quot;fmt&quot;
	&quot;io/ioutil&quot;
	&quot;oopexpertutil&quot;
)

func main() {

	var data string = &quot;Hello World!&quot;
	var dataAsBytes = []byte(data)

	fmt.Println(data)

	err := ioutil.WriteFile(&quot;hello_world.txt&quot;, dataAsBytes, 0644)

	fmt.Println(err)

	oopexpertutil.checkMe(err)

}

Disappointment...

This setup is still not working. You may have tried out all other answers that stick to workspace or package layout or "go modules" subject. The final point to consider to make this work is:

Change the name of the "checkMe" function of the referenced package to "CheckMe" and update the usage as well...

Go has some convention identifying exported functions from not exported functions of a package by a starting capital letter.

答案7

得分: -1

如果你只想在不同文件之间共享代码而不是不同的包,可以按照以下步骤进行操作:

你不需要使用import,只需将源文件放在同一个目录中,并在每个文件的顶部指定相同的package名称,然后你就可以直接引用所有公共(大写字母开头)的函数和类型,例如SomeFunction()而不是somepackage.SomeFunction()

英文:

If you just want to share code between separate files and not separate packages, here's how to do it:

You don't need to import, you just have to put the source files in the same directory and specify the same package name at the top of each file, and then you can access all the public (Uppercase) functions and types, by referencing them directly, that is, SomeFunction() and not somepackage.SomeFunction()

huangapple
  • 本文由 发表于 2015年6月17日 15:34:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/30885098.html
匿名

发表评论

匿名网友

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

确定