我使用过 GOPATH
,但对于我面临的当前问题,它没有帮助。我希望能够创建特定于项目的包:
myproject/
├── binary1.go
├── binary2.go
├── package1.go
└── package2.go
我尝试了多种方法,但如何让 package1.go
在 binary1.go
或 binary2.go
等中工作?
例如;我希望能够 import "package1"
然后能够运行 go build binary1.go
并且一切正常,而不会引发在 GOROOT
或 GOPATH
上找不到包的错误。我需要这种功能的原因是用于大型项目;我不想引用多个其他包或将它们保存在一个大文件中。
.go
文件都是同一个包的一部分,您不需要 import
文件在同一个包(即同一个目录)中。您提到在 GOPATH 之外工作,这是新的 Go 模块系统的功能之一。这个answer涵盖了模块结构、导入本地包、在一个模块中安排包、是否在单个存储库中有多个模块等。
git/repo/to/my/project
路径,否则您基本上无法导入本地子包?我只是不明白为什么有人会想要这种行为。如果您将项目移动到另一个位置(即 Docker 映像),您需要再次更改所有路径怎么办?我正在寻找为什么这如此复杂的答案。
Go依赖管理总结:
vgo 如果你的 go 版本是:x >= go 1.11
dep 或 vendor 如果你的 go 版本是:go 1.6 >= x < go 1.11
如果你的 go 版本是手动的:x < go 1.6
编辑 3:Go 1.11 有一个功能 vgo
,它将 replace dep
。
要使用 vgo
,请参阅 Modules 文档。 TLDR 如下:
export GO111MODULE=on
go mod init
go mod vendor # if you have vendor/ folder, will automatically integrate
go build
此方法在您的项目目录中创建一个名为 go.mod
的文件。然后您可以使用 go build
构建您的项目。如果设置了 GO111MODULE=auto
,则您的项目不能在 $GOPATH
中。
编辑 2:vendoring 方法仍然有效并且没有问题。 vendor
在很大程度上是一个手动过程,因为 dep
和 vgo
是这样创建的。
编辑1:虽然我的旧方法有效,但它不再是“正确”的方法。您应该使用 Go 1.6 中默认启用的 vendor 功能、vgo
或 dep
(目前); see。您基本上在 vendor
目录中添加“外部”或“依赖”包;在编译时,编译器将首先使用这些包。
成立。通过创建 package1
的子文件夹,然后在 binary1.go
和 binary2.go
脚本中使用 import "./package1"
导入,我可以使用 GOPATH
导入本地包,如下所示:
二进制1.go
...
import (
"./package1"
)
...
所以我当前的目录结构是这样的:
myproject/
├── binary1.go
├── binary2.go
├── package1/
│ └── package1.go
└── package2.go
我还应该注意相对路径(至少在 go 1.5 中)也可以工作;例如:
import "../packageX"
没有“本地包”之类的东西。磁盘上包的组织与包的任何父/子关系正交。包形成的唯一真正的层次结构是依赖树,在一般情况下它不反映目录树。
只需使用
import "myproject/packageN"
不要无缘无故地对抗构建系统。在任何重要的程序中每次导入保存十几个字符不是一个好的理由,因为例如,具有相对导入路径的项目是不可获取的。
导入路径的概念有一些重要的属性:
导入路径可以是全局唯一的。
与 GOPATH 一起,导入路径可以明确地转换为目录路径。
GOPATH 下的任何目录路径都可以明确地转换为导入路径。
使用相对导入路径会破坏上述所有内容。不要做。
PS:Go 编译器测试中的遗留代码中很少有地方使用相对导入。 ATM,这是完全支持相对导入的唯一原因。
import "myproject/packageN"
。 myproject
是保存我的项目的文件夹名称吗?
也许您正在尝试模块化您的包。我假设 package1
和 package2
在某种程度上是同一个包的一部分,但为了便于阅读,您将它们拆分为多个文件。
如果前一种情况是你的,你可以在这些多个文件中使用相同的包名,就像有相同的文件一样。
这是一个例子:
添加.go
package math
func add(n1, n2 int) int {
return n1 + n2
}
减法
package math
func subtract(n1, n2 int) int {
return n1 - n2
}
donthing.go
package math
func donothing(n1, n2 int) int {
s := add(n1, n2)
s = subtract(n1, n2)
return s
}
我不是围棋专家,这是我在 StackOveflow 上的第一篇文章,所以如果你有一些建议,它会很受欢迎。
自从引入 go.mod 后,我认为本地和外部包管理都变得更容易了。使用 go.mod,也可以在 GOPATH 之外创建 go 项目。
导入本地包:
创建文件夹 demoproject 并运行以下命令生成 go.mod 文件
go mod init demoproject
我在 demoproject 目录中有一个如下所示的项目结构。
├── go.mod
└── src
├── main.go
└── model
└── model.go
出于演示目的,在 model.go 文件中插入以下代码。
package model
type Employee struct {
Id int32
FirstName string
LastName string
BadgeNumber int32
}
在 main.go 中,我通过引用“demoproject/src/model”导入了 Employee 模型
package main
import (
"demoproject/src/model"
"fmt"
)
func main() {
fmt.Printf("Main Function")
var employee = model.Employee{
Id: 1,
FirstName: "First name",
LastName: "Last Name",
BadgeNumber: 1000,
}
fmt.Printf(employee.FirstName)
}
导入外部依赖:
只需在项目目录中运行 go get
命令。
例如:
go get -u google.golang.org/grpc
它应该在 go.mod 文件中包含模块依赖项
module demoproject
go 1.13
require (
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 // indirect
golang.org/x/text v0.3.2 // indirect
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150 // indirect
google.golang.org/grpc v1.26.0 // indirect
)
https://blog.golang.org/using-go-modules
can't load package: package .: no Go files in...
(在 go.mod 文件夹中构建)
我有一个类似的问题,我目前使用的解决方案使用 Go 1.11 模块。我有以下结构
- projects
- go.mod
- go.sum
- project1
- main.go
- project2
- main.go
- package1
- lib.go
- package2
- lib.go
我可以通过使用从 project1 和 project2 导入 package1 和 package2
import (
"projects/package1"
"projects/package2"
)
运行 go mod init projects
后。我可以使用 project1 和 project2 目录中的 go build
,也可以使用项目目录中的 go build -o project1/exe project1/*.go
。
这种方法的缺点是你所有的项目最终都会在 go.mod 中共享相同的依赖列表。我仍在寻找解决此问题的方法,但看起来它可能是根本性的。
您可以使用 replace
go mod init example.com/my/foo
foo/go.mod
module example.com/my/foo
go 1.14
replace example.com/my/bar => /path/to/bar
require example.com/my/bar v1.0.0
foo/main.go
package main
import "example.com/bar"
func main() {
bar.MyFunc()
}
酒吧/go.mod
module github.com/my/bar
go 1.14
酒吧/fn.go
package github.com/my/bar
import "fmt"
func MyFunc() {
fmt.Printf("hello")
}
导入本地包就像导入外部包一样
除了在 go.mod 文件中,您将外部包名称替换为本地文件夹。
文件夹的路径可以是完整的或相对的 /path/to/bar
或 ../bar
https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive
https://thewebivore.com/using-replace-in-go-mod-to-point-to-your-local-module/
要将“本地”包添加到您的项目,请添加一个文件夹(例如“package_name”)。并将您的实现文件放在该文件夹中。
src/github.com/GithubUser/myproject/
├── main.go
└───package_name
└── whatever_name1.go
└── whatever_name2.go
在您的 package main
中执行以下操作:
import "github.com/GithubUser/myproject/package_name"
其中 package_name
是文件夹名称,它必须与文件whatever_name1.go 和whatever_name2.go 中使用的包名称匹配。换句话说,具有子目录的所有文件都应该属于同一个包。
只要在导入中指定父文件夹的完整路径,就可以进一步嵌套更多子目录。
package myproject/package_name is not in GOROOT (/usr/lib/go-1.14/src/myproject/package_name)
跑:
go mod init yellow
然后创建一个文件 yellow.go
:
package yellow
func Mix(s string) string {
return s + "Yellow"
}
然后创建一个文件 orange/orange.go
:
package main
import "yellow"
func main() {
s := yellow.Mix("Red")
println(s)
}
然后构建:
go build
https://golang.org/doc/code.html
在 bash 终端中
mkdir <module name>
cd <module name>
go mod init <module name>
touch <module name>.go
在
cd ..
mkdir main
cd main
go mod init main
touch main.go
创建导入“<模块名称>”的主包
go mod edit -replace=<module name>=<module path>
go mod tidy
如果您想了解 go 的背景中发生的事情,请查看每个 go.mod,您的文件夹结构将如下所示:
- Project
- <module name>
- <module name>.go
- go.mod
- main
- main.go
- go.mod
go run .
或者
go build &&
./main.exe
import "../package1"