英文:
How does modular code work in Go?
问题
没有来自C/编译语言背景的经验,我发现很难理解如何使用Go的包机制来创建模块化代码。
在Python中,要导入一个模块并访问它的函数等内容,只需要简单地写上:
import foo
其中foo.py是要导入的模块的名称,它位于同一目录下。否则,您可以在子文件夹中添加一个空的__init__.py
文件,并通过以下方式访问模块:
from subfolder import foo
然后,您可以通过模块名称直接引用函数,例如y = foo.bar(y)
。这使得将代码的逻辑部分分离变得很容易。
然而,在Go中,您需要在源文件中指定包名称,例如:
package foo
在'foo'模块的顶部,然后可以通过以下方式导入:
import (
"foo"
)
然后通过该方式引用,即y := foo.Bar(x)
。但我无法理解这在实践中是如何工作的。golang.org上相关的文档似乎很简洁,并且面向那些有更多(任何)使用makefile和编译器经验的人。
请有人清楚地解释一下如何在Go中模块化代码,正确的项目结构以及编译过程是如何工作的?
英文:
Not having come from a C/compiled languages background, I'm finding it hard to get to grips with using Go's packages mechanism to create modular code.
In Python, to import a module and get access to it's functions and whatnot, it's a simple case of
import foo
where foo.py is the name of the module you want to import in the same directory. Otherwise you can add an empty __init__.py
into a subfolder and access the modules via
from subfolder import foo
You can then access functions by simply referencing them through the module name, e.g. y = foo.bar(y)
. This makes it easy to separate logical pieces of code from one another.
In Go however, you specify the package name in the source file itself, e.g.
package foo
at the top of the 'foo' module, which you can then supposedly import through
import (
"foo"
)
and then refer to it through that, i.e. y := foo.Bar(x)
. But what I can't wrap my head around is how this works in practice. The relevant docs on golang.org seem terse, and directed to people with more (any) experience using makefiles and compilers.
Can someone please clearly explain how you are meant to modularise your code in Go, the right project structure to do so, and how the compilation process works?
答案1
得分: 22
模块化
-
同一个包中的多个文件
- 这就是它听起来的样子。在同一个目录中有一堆以相同的
package <name>
指令开头的文件意味着它们被 Go 视为一个大的代码集合。你可以从b.go
中透明地调用a.go
中的函数。这主要是为了代码组织的好处。 - 一个虚构的例子是一个“博客”包,可能会以
blog.go
(主文件)、entry.go
和server.go
的方式布局。这取决于你。虽然你可以在一个大文件中编写一个博客包,但这往往会影响可读性。
- 这就是它听起来的样子。在同一个目录中有一堆以相同的
-
多个包
- 标准库就是这样做的。基本上,你创建模块,可以选择将其安装到
$GOROOT
中。你编写的任何程序都可以import "<name>"
,然后调用<name>.someFunction()
- 实际上,任何独立的或共享的组件都应该编译成包。回到上面的博客包,如果你想要添加一个新闻订阅,你可以将
server.go
重构为一个包。然后,blog.go
和news.go
都可以import "server"
。
- 标准库就是这样做的。基本上,你创建模块,可以选择将其安装到
编译
我目前使用带有 Makefile 的 gomake。Go 安装包含了一些很棒的用于 make 的包含文件,简化了包或命令的创建。这并不难,最好的方法是查看开源项目中的示例 makefile,并阅读《如何编写 Go 代码》。
英文:
Wiki answer, please feel free to add/edit.
Modularization
-
Multiple files in the same package
- This is just what it sounds like. A bunch of files in the same directory that all start with the same
package <name>
directive means that they are treated as one big set of code by Go. You can transparently call functions ina.go
fromb.go
. This is mostly for the benefit of code organization. - A fictional example would be a "blog" package might be laid out with
blog.go
(the main file),entry.go
, andserver.go
. It's up to you. While you could write a blog package in one big file, that tends to affect readability.
- This is just what it sounds like. A bunch of files in the same directory that all start with the same
-
Multiple packages
- The standard library is done this way. Basically you create modules and optionally install them into
$GOROOT
. Any program you write canimport "<name>"
and then call<name>.someFunction()
- In practice any standalone or shared components should be compiled into packages. Back to the blog package above, If you wanted to add a news feed, you could refactor server.go into a package. Then both
blog.go
andnews.go
would bothimport "server"
.
- The standard library is done this way. Basically you create modules and optionally install them into
Compilation
I currently use gomake with Makefiles. The Go installation comes with some great include files for make that simplify the creation of a package or a command. It's not hard and the best way to get up to speed with these is to just look at sample makefiles from open source projects and read "How to Write Go Code".
答案2
得分: 1
除了包组织之外,像Python中的pip一样,使用dep(https://github.com/golang/dep)来管理Go包。如果你在现有的Go包上使用它,它将自动构建使用的所有包的版本依赖树。当切换到生产服务器时,dep ensure将使用Gopkg.toml安装所有所需的包。
只需使用dep ensure -add <包名>,dep的其他命令包括:
命令:
init 设置一个新的Go项目,或迁移现有项目
status 报告项目依赖的状态
ensure 确保依赖安全地存储在项目中
version 显示dep的版本信息
check 检查导入、Gopkg.toml和Gopkg.lock是否同步
示例:
dep init 设置一个新项目
dep ensure 安装项目的依赖
dep ensure -update 更新所有依赖的锁定版本
dep ensure -add github.com/pkg/errors 向项目添加一个依赖
英文:
In addition to the package organisation, Like pip in python, use dep https://github.com/golang/dep for go package management. if you use it on existing go package it will automatically build the dependency tree with versions for all the packages being used. when shifting to production server, dep ensure will use Gopkg.toml to install all the required packages.
Just use dep ensure -add <package name>, other commands for dep are:
Commands:
init Set up a new Go project, or migrate an existing one
status Report the status of the project's dependencies
ensure Ensure a dependency is safely vendored in the project
version Show the dep version information
check Check if imports, Gopkg.toml, and Gopkg.lock are in sync
Examples:
dep init set up a new project
dep ensure install the project's dependencies
dep ensure -update update the locked versions of all dependencies
dep ensure -add github.com/pkg/errors add a dependency to the project
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论