将项目拆分为子文件夹

abo*_*nec 16 go

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

我想要这个代码结构:

??? main.go
??? models
    ??? user.go
Run Code Online (Sandbox Code Playgroud)

main.go是:

package main

import (
  "fmt"
  "./models"
)

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

}
Run Code Online (Sandbox Code Playgroud)

而user.go是:

package models

type User struct {
  Login string
}
Run Code Online (Sandbox Code Playgroud)

但是主程序包中没有定义用户,导入引发警告"导入但未使用".

我究竟做错了什么?我的项目很简单(不是这样的例子,只是文件很少(控制器和模型)),我想要一个简单的结构.

也许我是以完全错误的方式做到的?

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

Jim*_*mbo 14

免责声明:我不知道这种方法有任何缺点 - 可能有很多,例如不再使用常见的工具,部署期间的问题,容器化,不是惯用等等......然而,这确实实现了你的原始问题for - 随意评论!:-)

另外:你无论如何都可以做子目录......但这提供了一种"命名空间"的感觉

我最近通过使用go模块实现了这一目标.

Golang引入模块,初步选择在支持去v1.11.1其目的是彻底清除,坦率地说,荒谬的$GOPATH必要性.您现在不仅可以在任何普通目录中使用版本化依赖项,例如~/development,您基本上可以使用类似名称空间和子目录的内容.您可以通过使用以下环境变量调用go命令来启用此功能:GO111MODULE=on.

Go v1.11.3预计默认启用模块,预计将于2019年8月启用.


这是一个示例目录结构(通常可以在其他一些语言中找到).

~/Dev/my-app
 ??? src/
 ?   ??? one/
 ?   ?   ??? two/
 ?   ?   ?   ??? two.go
 ?   ?   ??? one.go
 ?   ??? zero.go
 ??? go.mod
 ??? app.go
Run Code Online (Sandbox Code Playgroud)

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

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

以下是您需要做的事情:

go.mod

module my-app
Run Code Online (Sandbox Code Playgroud)

two.go

package two

func Two() string {
    return "I'm totally not supposed to be using go modules for this"
}
Run Code Online (Sandbox Code Playgroud)

app.go

package main

import "my-app/src/one/two"

func main() {
    two.Two()
}
Run Code Online (Sandbox Code Playgroud)

如果您要将另一个文件放在两个/中,那么two.TheNewFunc()只要您TheNewFunc()在新文件中可用,就可以使用它.

我创建了一个非常简单的GitHub仓库,您可以将其作为演示进行检查.


Von*_*onC 8

你的导入应该是绝对的:

import "github.com/abonec/go_import_problem/models"
Run Code Online (Sandbox Code Playgroud)

如果您不想将项目导出到外部参照,则可以执行以下操作:

import "go_import_problem/models"
Run Code Online (Sandbox Code Playgroud)

(那就是:" the name of your project folder accessible by GOPATH/your package")

请参阅" 如何在golang中使用自定义包? ".

你会用:

models.User
Run Code Online (Sandbox Code Playgroud)

Effective Go中所述:

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


kostix 在评论中添加:

重申一下,Go包的名称总是绝对的(也就是说,没有相对的包名,既没有./也没有../或类似的东西),但这些名称"锚定"到其中一个所谓的工作空间中$GOPATH.

当Go搜索包时,它会查看工作空间并尝试按顺序查找每个包中的包.
搜索不是递归的.
不,不需要在包路径中对URL进行编码 - 除非您想要将包公开.


abo*_*nec -7

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

import "./models"
Run Code Online (Sandbox Code Playgroud)

对于 struct User 你应该将其用作

models.User
Run Code Online (Sandbox Code Playgroud)