如何使用“内部”包?

问题描述 投票:15回答:3

我尝试了解如何使用“内部”包来组织代码。让我展示一下我的结构:

project/
  internal/
    foo/
      foo.go # package foo
    bar/
      bar.go # package bar
  main.go

# here is the code from main.go
package main

import (
  "project/internal/foo"
  "project/internal/bar"
)

project/在GOPATH树之外。无论我尝试从main.go导入的任何路径都没有效果,唯一正常工作的案例是import "./internal/foo|bar"。我认为我做错了什么或者一般来说“内部”包装的想法是错误的。请问有人能让事情更清楚吗?

UPDATE

上面的例子是正确的,我唯一需要的是在project/下放置$GOPATH/src文件夹。因此,如果我们只从project/internal/foo|bar子树而不是从外部导入它,那么就像project/这样的导入路径是可行的。

go
3个回答
13
投票

包裹必须位于您的$GOPATH才能进口。你用import "./internal/foo|bar"给出的例子是有效的,因为它进行了本地导入。 internal只使得不与internal目录共享根目录的代码无法导入internal中的包。

如果你把所有这些放在你的gopath然后尝试从OuterFolder/project2/main.go不同的位置导入OuterFolder包含projectproject2然后import "../../project/internal/foo"将失败。由于不满足这个条件,它也会因为import "foo"或你试过的任何其他方式而失败;

如果导入代码位于以“internal”目录的父级为根的树之外,则不允许导入包含元素“internal”的路径。

现在,如果你有路径$GOPATH/src/project然后你可以从import "foo"内做import "bar"$GOPATH/src/project/main.go,导入将成功。然而,project下面没有包含的东西将无法导入foobar


6
投票

以下方式更具可扩展性,尤其是当您计划构建多个二进制文件时

github.com/servi-io/api
├── cmd/
│   ├── servi/
│   │   ├── cmdupdate/
│   │   ├── cmdquery/
│   │   └── main.go
│   └── servid/
│       ├── routes/
│       │   └── handlers/
│       ├── tests/
│       └── main.go
├── internal/
│   ├── attachments/
│   ├── locations/
│   ├── orders/
│   │   ├── customers/
│   │   ├── items/
│   │   ├── tags/
│   │   └── orders.go
│   ├── registrations/
│   └── platform/
│       ├── crypto/
│       ├── mongo/
│       └── json/

cmd/中的文件夹表示您要构建的二进制文件的数量。

for more


0
投票

还要检查:当你使用外部导入的对象类型时:确保你在前面加上他们所在的命名空间。作为一个golang新手,我不知道我必须这样做,并且想知道为什么VS代码只是在我保存时删除了我的导入(因为没有被使用)。这是因为我必须在导入的对象前面添加命名空间名称:

Example:
import (
    "myInternalPackageName"  // works fine as long as you follow all instructions in this thread
)

//Usage in code: 
myInternalPackageName.TheStructName   // prefix it, or it won't work. 

如果你没有在对象/结构名称之前放置名称空间前缀,VS代码只是删除你的导入未被使用,然后你仍然有错误:“找不到TheStructName”...这非常令人困惑,并且我必须通过命令行在没有VS代码的情况下进行构建才能理解这一点。

关键是:我必须在实际使用该内部包中的结构时指定包前缀。

如果您不想在使用导入的对象时使用限定符前缀,请使用:

import . "thePath"    // Can use contents without prefixing. 

参考:What does the '.' (dot or period) in a Go import statement do?

© www.soinside.com 2019 - 2024. All rights reserved.