202

我已经使用过GOPATH,但对于我面临的当前问题,它没有帮助。我希望能够创建特定于项目的包:

myproject/
├── binary1.go
├── binary2.go
├── package1.go
└── package2.go

我尝试了多种方法,但我如何才能package1.gobinary1.goor thebinary2.go等中工作?

例如; 我希望能够import "package1"然后能够运行go build binary1.go并且一切正常,而不会引发无法在GOROOTor上找到包的错误GOPATH。我需要这种功能的原因是用于大型项目;我不想引用多个其他包或将它们保存在一个大文件中。

4

9 回答 9

184

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替换 dep.

要使用vgo,请参阅模块文档。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很大程度上是一个手动过程,因此depvgo被创建。


编辑1:虽然我的旧方法有效,但它不再是“正确”的方法。您应该使用Go 1.6 中默认启用的供应商功能,vgo或(目前);。您基本上在目录中添加“外部”或“依赖”包;在编译时,编译器将首先使用这些包。depvendor


成立。GOPATH我可以通过创建一个子文件夹package1然后使用import "./package1"inbinary1.gobinary2.go这样的脚本导入本地包:

二进制1.go

...
import (
        "./package1"
      )
...

所以我当前的目录结构是这样的:

myproject/
├── binary1.go
├── binary2.go
├── package1/
│   └── package1.go
└── package2.go

我还应该注意相对路径(至少在 go 1.5 中)也可以工作;例如:

import "../packageX"
于 2013-07-09T03:43:35.570 回答
73

没有“本地包”之类的东西。磁盘上包的组织与包的任何父/子关系正交。包形成的唯一真正的层次结构是依赖树,在一般情况下它不反映目录树。

只需使用

import "myproject/packageN"

不要无缘无故地对抗构建系统。在任何重要的程序中每次导入保存十几个字符不是一个好的理由,因为例如,具有相对导入路径的项目是不可获取的。

导入路径的概念有一些重要的属性:

  • 导入路径可以是全局唯一的。
  • 与 GOPATH 一起,导入路径可以明确地转换为目录路径。
  • GOPATH 下的任何目录路径都可以明确地转换为导入路径。

使用相对导入路径会破坏上述所有内容。不要做。

PS:Go 编译器测试中的遗留代码中很少有地方使用相对导入。ATM,这是完全支持相对导入的唯一原因。

于 2013-07-09T06:11:27.857 回答
52

也许您正在尝试模块化您的包。我假设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 上的第一篇文章,所以如果你有一些建议,它会很受欢迎。

于 2015-02-08T04:31:57.757 回答
42

自从引入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

于 2020-01-25T20:40:29.187 回答
25

我有一个类似的问题,我目前使用的解决方案使用 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。我可以go build从 project1 和 project2 目录中使用,也可以go build -o project1/exe project1/*.go从项目目录中使用。

这种方法的缺点是你所有的项目最终都会在 go.mod 中共享相同的依赖列表。我仍在寻找解决此问题的方法,但看起来它可能是根本性的。

于 2018-10-09T20:31:26.467 回答
13

您可以使用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

于 2020-03-29T14:27:03.303 回答
9

要将“本地”包添加到您的项目,请添加一个文件夹(例如“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 中使用的包名称匹配。换句话说,具有子目录的所有文件都应该属于同一个包。

只要在导入中指定父文件夹的完整路径,就可以进一步嵌套更多子目录。

于 2017-05-17T05:40:41.027 回答
2

跑:

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

于 2020-11-29T01:01:34.410 回答
-1

在 bash 终端中

mkdir <module name>  
cd <module name>  
go mod init <module name>  
touch <module name>.go
  • <module name>在.go中创建 go 包
cd ..  
mkdir main  
cd main  
go mod init main  
touch main.go
  • 创建导入“ <module name>”的主包
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
于 2021-05-16T16:32:56.637 回答