将Go项目拆分为子文件夹。

huangapple go评论78阅读模式
英文:

Break up go project into subfolders

问题

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

我想要这样的代码结构:

├── 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
}

但是 User 在 main 包中没有定义,并且导入会引发警告 "imported and not used"。

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

也许我完全错了吗?

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

英文:

I want to break my project up to subfolders.

I want this code structure:

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

Where main.go is:

package main

import (
  "fmt"
  "./models"
)

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

}

And user.go is:

package models

type User struct {
  Login string
}

But User is not defined in main package and import raise warning "imported and not used".

What am I doing wrong? My project is simple (not such a example but just with few files (controllers and models)) and I want a simple structure.

Maybe I doing it in completely wrong way?

Problem project is here: https://github.com/abonec/go_import_problem

答案1

得分: 36

我最近通过使用go modules来实现这个。

截至go v1.11.1,Golang引入了初步的模块支持,旨在完全消除 $GOPATH 的需求。现在你可以在任何普通目录(如 ~/development)中使用版本化的依赖项,而且你基本上可以拥有类似命名空间和子目录的东西。你可以通过使用以下环境变量来启用此功能GO111MODULE=on

Go v1.11.3 预计会默认启用模块,计划于2019年8月发布。


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

~/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 的函数,在 app.go 中可以通过 my-app/src/one/two 导入。

以下是实现这一点的步骤:

go.mod

module my-app

two.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() 可用,你就可以简单地使用 two.TheNewFunc()

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

英文:

I recently achieved this by using go modules.

Golang introduced preliminary opt-in support for modules as of go v1.11.1 which is intended to completely remove the, frankly, absurd $GOPATH necessity. Not only can you now have versioned dependencies in any normal directory such as ~/development, but you can basically have something that looks like namespaces and sub-directories. You can enable this feature by invoking the go command with the following environment variable: GO111MODULE=on.

Go v1.11.3 expects to enable modules by default and is slated for August 2019.


Here is an example directory structure (that you might find typically in some other languages).

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

The application is called my-app, which will be the module name for app.go. We define this once in go.mod and then each of all the other go files in subdirectories will automatically be importable as if they were namespaced.

Given the above, two.go, assuming it contains a function named Two, will be importable in app.go by using my-app/src/one/two.

Here's what you need to do to achieve this:

go.mod

module my-app

two.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()
}

If you were to place another file within two/, then you would simply use two.TheNewFunc() as long as you made TheNewFunc() available within the new file.

I created a very simple GitHub repo which you can check out as a demonstration.

答案2

得分: 10

你的导入语句应该是绝对路径的形式:

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

如果你不想将项目导出到外部引用中,可以使用:

import "go_import_problem/models"

(即:GOPATH/你的包所在的项目文件夹的名称

参考:如何在Go中使用自定义包?

然后你可以使用:

models.User

正如在Effective Go中提到的:

导入包的代码会使用包的名称来引用其内容,因此包中的导出名称可以利用这一点避免冗余。
不要使用import .的形式,这样可以简化必须在包外运行的测试,但在其他情况下应避免使用。)


kostix评论中补充道

重申一下,Go包的名称始终是绝对路径(即没有相对包名,无论是使用./还是../等),但这些名称是“锚定”到$GOPATH中列出的工作区之一的。

当Go搜索包时,它会按顺序在每个工作区中查找包。
搜索不是递归的。
不,没有要求在包路径中编码URL,除非你想将包公开。

英文:

Your import should be an absolute one:

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

If you don't want to export your project to an external referential, you can do a:

import "go_import_problem/models"

(That is: "the name of your project folder accessible by GOPATH/your package")

See "How to use custom packages in golang?".

And you would use:

models.User

As mentioned in Effective Go:

> The importer of a package will use the name to refer to its contents, so exported names in the package can use that fact to avoid stutter.
(Don't use the import . notation, which can simplify tests that must run outside the package they are testing, but should otherwise be avoided.)


kostix adds in the comments:

> to reiterate, names of Go packages are always absolute (that is, there's no relative package names, neither with ./ nor with ../ or anything like that) but that names are "anchored" to one of the so-called workspaces listed in $GOPATH.
>
> When Go searches for a package, it looks through workspaces and tries to find a package in each of them, in order.
The search is not recursive.
And no, there's no requirement to encode URLs in package paths -- unless you want to make your package public.

答案3

得分: 0

你需要通过包名来限定一个包中的项目。

所以,

fmt.Println(models.User{"new_user"})
英文:

You need to qualify items in in a package by its package name

So

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

答案4

得分: 0

将一个单一项目拆分为子文件夹并不是推荐的组织Go项目的方式,这就是为什么基本上没有好的方法来实现你想要的效果。

如果项目真的非常大,而且太复杂以至于无法作为一个单一的包来处理,考虑将其拆分为几个完全独立的包,而不是特殊的子目录包。这样做的好处是迫使你清晰地思考内部API的设计。

英文:

Breaking up a single project into subfolders is not the recommended way of structuring a go project, which is why there is basically no good way to do what you want.

If the project is really large, and too unwieldy to make a single package, consider splitting it into several totally distinct packages, rather than special sub-directory packages. This has the advantage of forcing you to think cleanly about your internal APIs.

答案5

得分: -1

这些包与你的"go/src"文件夹中的代码相关联。

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

所以在"main.go"中:

package main

import (
  "fmt"
  "myAwesomeProject/models"
)

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

英文:

The packages are referenced in code in relation to your "go/src" folder

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

So in main.go

package main

import (
  "fmt"
  "myAwesomeProject/models"
)

Similarly packages can reference each other using the same convention.

答案6

得分: -7

你应该使用导入的对象的导入名称。例如,如果你使用以下代码导入了结构体 User:

import "./models"

那么你应该使用以下方式来使用它:

models.User
英文:

You should use your imported objects by it's imported names. For example if you

import "./models"

with struct User you should use it as

models.User

huangapple
  • 本文由 发表于 2014年4月18日 21:11:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/23154898.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定