【问题标题】:Break up go project into subfolders将 go 项目分解为子文件夹
【发布时间】:2014-06-03 00:13:08
【问题描述】:

我想将我的项目分解为子文件夹。

我想要这个代码结构:

├── main.go
└── models
    └── user.go

main.go 在哪里:

package main

import (
  "fmt"
  "./models"
)

func main(){
  fmt.Println(User{"new_user"})

}

而 user.go 是:

package models

type User struct {
  Login string
}

但用户未在主包中定义,导入引发警告“已导入且未使用”。

我做错了什么?我的项目很简单(不是这样的示例,但只有几个文件(控制器和模型)),我想要一个简单的结构。

也许我的做法完全错误?

问题项目在这里:https://github.com/abonec/go_import_problem

【问题讨论】:

    标签: go


    【解决方案1】:

    我最近通过使用 go modules 实现了这一点。

    go v1.11.1 开始,Golang 引入了对模块的初步选择加入支持,坦率地说,这是为了彻底消除荒谬的 $GOPATH 必要性。您现在不仅可以在任何普通目录(例如~/development)中拥有版本化的依赖项,而且您基本上可以拥有看起来像命名空间和子目录的东西。您可以通过使用以下环境变量调用 go 命令来enable this featureGO111MODULE=on

    Go v1.11.3 预计将在 2019 年 8 月发布 enable modules by default


    这是一个示例目录结构(您可能会在其他一些语言中找到它)。

    ~/Dev/my-app
     ├── src/
     │   ├── one/
     │   │   ├── two/
     │   │   │   └── two.go
     │   │   └── one.go
     │   └── zero.go
     ├── go.mod
     └── app.go
    

    应用程序名为my-app,它将是app.go 的模块名称。我们在 go.mod 中定义一次,然后子目录中的所有其他 go 文件将自动导入,就像它们被命名空间一样。

    鉴于上述情况,two.go,假设它包含一个名为 Two 的函数,将可以通过使用 my-app/src/one/twoapp.go 中导入。

    以下是您需要做的事情:

    go.mod

    module my-app
    

    两个.go

    package two
    
    func Two() string {
        return "I'm totally not supposed to be using go modules for this"
    }
    

    app.go

    package main
    
    import "my-app/src/one/two"
    
    func main() {
        two.Two()
    }
    

    如果您要在两个 / 中放置另一个文件,那么您只需使用 two.TheNewFunc(),只要您在新文件中提供了 TheNewFunc()

    我创建了一个非常简单的GitHub repo,您可以查看它作为演示。

    【讨论】:

    • 你能解释一下那个字符串中的注释吗:“我完全不应该为此使用 go 模块”。你是什​​么意思我们不应该为此使用模块?
    • @NathanLutterman 在我看到这很普遍之前,我自然认为纯粹主义者会讨厌 Golang 通常不做的任何事情。这种态度在 Go 程序员中很常见。但是我现在可以删除它,因为它看起来很标准:)
    • 是否可以在one 包内添加import "my-app/src/one/two"
    • @cybercoder 你想用一行导入多个包吗?还是只是普通的导入?
    • @Jimbo 很明显,我需要在你的结构中导入two 包内的one 包。
    【解决方案2】:

    您的导入应该是绝对的:

    import "github.com/abonec/go_import_problem/models"
    

    如果您不想将项目导出到外部引用,您可以这样做:

    import "go_import_problem/models"
    

    (即:“the name of your project folder accessible by GOPATH/your package”)

    见“How to use custom packages in golang?”。

    你会使用:

    models.User
    

    Effective Go中所述:

    包的导入器将使用名称来引用其内容,因此包中的导出名称可以使用该事实来避免卡顿。
    不要使用 import . 表示法,这可以简化必须在他们正在测试的包之外运行的测试,否则应该避免。)


    kostix 添加in the comments

    重申一下,Go 包的名称始终是绝对的(也就是说,没有相对的包名,./../ 或类似名称都没有)但是 名称被“锚定”到 $GOPATH 中列出的所谓工作区之一。

    当 Go 搜索一个包时,它会查看工作区并尝试按顺序在每个工作区中找到一个包。
    搜索不是递归的。
    不,不需要在包路径中对 URL 进行编码——除非你想公开你的包。

    【讨论】:

    • 我不打算将任何这些代码存储在 github 中。我应该在我的项目树中导入和更改什么?
    • @Abonec 然后import "models" 应该足够了
    • 它不起作用,并且在以下任何位置都找不到包“模型”:/usr/local/go/src/pkg/conf(来自 $GOROOT)/home/abonec/gopath/src /conf(来自 $GOPATH)
    • @Abonec 请记住,GOPATH 不引用项目。它引用了一个“工作区”。在每个工作空间下,您可以找到一个或多个文件夹,每个文件夹代表一个项目。
    • @Abonec 是的,或者您可以定义多个工作区,您的项目的子集可以在这些工作区下存在(因为GOPATH 可以列出多个工作区文件夹)
    【解决方案3】:

    您需要通过包名来限定包中的项目

    所以

    fmt.Println(models.User{"new_user"})
    

    【讨论】:

      【解决方案4】:

      将单个项目分解为子文件夹不是构建 Go 项目的推荐方式,这就是为什么基本上没有好方法可以做你想做的事情。

      如果项目真的很大,并且太笨重而无法制作单个包,请考虑将其拆分为几个完全不同的包,而不是特殊的子目录包。这样做的好处是迫使您清楚地考虑您的内部 API。

      【讨论】:

      • 我的项目不是特别大。我只想通过它的域逻辑将其分解为 30-50 行的文件。但我不明白怎么做。
      • @Abonec 单个包可以有多个文件——即 server.go、models.go、otherthings.go、handlers.go 等。如果将它们拆分为子包,这些都可以在 package main 中没有“意义”。
      【解决方案5】:

      在与您的“go/src”文件夹相关的代码中引用了这些包

      └── go
          └── src
              └── myAwesomeProject
                  ├── main.go
                  └── models
                      └── user.go
      

      所以在main.go

      package main
      
      import (
        "fmt"
        "myAwesomeProject/models"
      )
      

      类似的包可以使用相同的约定相互引用。

      【讨论】:

      • 这个答案可能是正确的,但它肯定缺少像我这样的 Go 初学者需要的细节。什么是“go/src”文件夹?这是一个神奇的地方吗?
      【解决方案6】:

      您应该通过导入的名称来使用导入的对象。例如,如果你

      import "./models"
      

      使用 struct User 你应该把它当作

      models.User
      

      【讨论】:

      • 如果您希望您的项目被其他人使用,并且与 go toolcahin 完全兼容,请不要使用相对导入。始终通过正确的包名称导入。
      • @JumB 在这个例子中我应该如何导入?
      • 通过您工作区中的正确路径。见golang.org/doc/code.html#Organization
      猜你喜欢
      • 1970-01-01
      • 2016-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      相关资源
      最近更新 更多