英文:
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/你的包所在的项目文件夹的名称
)
然后你可以使用:
models.User
正如在Effective Go中提到的:
导入包的代码会使用包的名称来引用其内容,因此包中的导出名称可以利用这一点避免冗余。
(不要使用import .
的形式,这样可以简化必须在包外运行的测试,但在其他情况下应避免使用。)
重申一下,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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论