26 About the go command go命令行
About the go command go命令行
The Go distribution includes a command, named "go
", that automates the downloading, building, installation, and testing of Go packages and commands. This document talks about why we wrote a new command, what it is, what it's not, and how to use it.
Motivation
You might have seen early Go talks in which Rob Pike jokes that the idea for Go arose while waiting for a large Google server to compile. That really was the motivation for Go: to build a language that worked well for building the large software that Google writes and runs. It was clear from the start that such a language must provide a way to express dependencies between code libraries clearly, hence the package grouping and the explicit import blocks. It was also clear from the start that you might want arbitrary syntax for describing the code being imported; this is why import paths are string literals.
An explicit goal for Go from the beginning was to be able to build Go code using only the information found in the source itself, not needing to write a makefile or one of the many modern replacements for makefiles. If Go needed a configuration file to explain how to build your program, then Go would have failed.
At first, there was no Go compiler, and the initial development focused on building one and then building libraries for it. For expedience, we postponed the automation of building Go code by using make and writing makefiles. When compiling a single package involved multiple invocations of the Go compiler, we even used a program to write the makefiles for us. You can find it if you dig through the repository history.
The purpose of the new go command is our return to this ideal, that Go programs should compile without configuration or additional effort on the part of the developer beyond writing the necessary import statements.
Configuration versus convention
The way to achieve the simplicity of a configuration-free system is to establish conventions. The system works only to the extent that those conventions are followed. When we first launched Go, many people published packages that had to be installed in certain places, under certain names, using certain build tools, in order to be used. That's understandable: that's the way it works in most other languages. Over the last few years we consistently reminded people about the goinstall
command (now replaced by go get
) and its conventions: first, that the import path is derived in a known way from the URL of the source code; second, that the place to store the sources in the local file system is derived in a known way from the import path; third, that each directory in a source tree corresponds to a single package; and fourth, that the package is built using only information in the source code. Today, the vast majority of packages follow these conventions. The Go ecosystem is simpler and more powerful as a result.
We received many requests to allow a makefile in a package directory to provide just a little extra configuration beyond what's in the source code. But that would have introduced new rules. Because we did not accede to such requests, we were able to write the go command and eliminate our use of make or any other build system.
It is important to understand that the go command is not a general build tool. It cannot be configured and it does not attempt to build anything but Go packages. These are important simplifying assumptions: they simplify not only the implementation but also, more important, the use of the tool itself.
Go's conventions
The go
command requires that code adheres to a few key, well-established conventions.
First, the import path is derived in an known way from the URL of the source code. For Bitbucket, GitHub, Google Code, and Launchpad, the root directory of the repository is identified by the repository's main URL, without the http://
prefix. Subdirectories are named by adding to that path. For example, the Go example programs are obtained by running
git clone https://github.com/golang/example
and thus the import path for the root directory of that repository is "github.com/golang/example
". The stringutilpackage is stored in a subdirectory, so its import path is "github.com/golang/example/stringutil
".
These paths are on the long side, but in exchange we get an automatically managed name space for import paths and the ability for a tool like the go command to look at an unfamiliar import path and deduce where to obtain the source code.
Second, the place to store sources in the local file system is derived in a known way from the import path, specifically $GOPATH/src/<import-path>
. If unset, $GOPATH
defaults to a subdirectory named go
in the user's home directory. If $GOPATH
is set to a list of paths, the go command tries <dir>/src/<import-path>
for each of the directories in that list.
Each of those trees contains, by convention, a top-level directory named "bin
", for holding compiled executables, and a top-level directory named "pkg
", for holding compiled packages that can be imported, and the "src
" directory, for holding package source files. Imposing this structure lets us keep each of these directory trees self-contained: the compiled form and the sources are always near each other.
These naming conventions also let us work in the reverse direction, from a directory name to its import path. This mapping is important for many of the go command's subcommands, as we'll see below.
Third, each directory in a source tree corresponds to a single package. By restricting a directory to a single package, we don't have to create hybrid import paths that specify first the directory and then the package within that directory. Also, most file management tools and UIs work on directories as fundamental units. Tying the fundamental Go unit—the package—to file system structure means that file system tools become Go package tools. Copying, moving, or deleting a package corresponds to copying, moving, or deleting a directory.
Fourth, each package is built using only the information present in the source files. This makes it much more likely that the tool will be able to adapt to changing build environments and conditions. For example, if we allowed extra configuration such as compiler flags or command line recipes, then that configuration would need to be updated each time the build tools changed; it would also be inherently tied to the use of a specific toolchain.
Getting started with the go command
Finally, a quick tour of how to use the go command. As mentioned above, the default $GOPATH
on Unix is $HOME/go
. We'll store our programs there. To use a different location, you can set $GOPATH
; see How to Write Go Code for details.
We first add some source code. Suppose we want to use the indexing library from the codesearch project along with a left-leaning red-black tree. We can install both with the "go get
" subcommand:
$ go get github.com/google/codesearch/index
$ go get github.com/petar/GoLLRB/llrb
$
Both of these projects are now downloaded and installed into $HOME/go
, which contains the two directoriessrc/github.com/google/codesearch/index/
and src/github.com/petar/GoLLRB/llrb/
, along with the compiled packages (in pkg/
) for those libraries and their dependencies.
Because we used version control systems (Mercurial and Git) to check out the sources, the source tree also contains the other files in the corresponding repositories, such as related packages. The "go list
" subcommand lists the import paths corresponding to its arguments, and the pattern "./...
" means start in the current directory ("./
") and find all packages below that directory ("...
"):
$ cd $HOME/go/src
$ go list ./...
github.com/google/codesearch/cmd/cgrep
github.com/google/codesearch/cmd/cindex
github.com/google/codesearch/cmd/csearch
github.com/google/codesearch/index
github.com/google/codesearch/regexp
github.com/google/codesearch/sparse
github.com/petar/GoLLRB/example
github.com/petar/GoLLRB/llrb
$
We can also test those packages:
$ go test ./...
? github.com/google/codesearch/cmd/cgrep [no test files]
? github.com/google/codesearch/cmd/cindex [no test files]
? github.com/google/codesearch/cmd/csearch [no test files]
ok github.com/google/codesearch/index 0.203s
ok github.com/google/codesearch/regexp 0.017s
? github.com/google/codesearch/sparse [no test files]
? github.com/petar/GoLLRB/example [no test files]
ok github.com/petar/GoLLRB/llrb 0.231s
$
If a go subcommand is invoked with no paths listed, it operates on the current directory:
$ cd github.com/google/codesearch/regexp
$ go list
github.com/google/codesearch/regexp
$ go test -v
=== RUN TestNstateEnc
--- PASS: TestNstateEnc (0.00s)
=== RUN TestMatch
--- PASS: TestMatch (0.00s)
=== RUN TestGrep
--- PASS: TestGrep (0.00s)
PASS
ok github.com/google/codesearch/regexp 0.018s
$ go install
$
That "go install
" subcommand installs the latest copy of the package into the pkg directory. Because the go command can analyze the dependency graph, "go install
" also installs any packages that this package imports but that are out of date, recursively.
Notice that "go install
" was able to determine the name of the import path for the package in the current directory, because of the convention for directory naming. It would be a little more convenient if we could pick the name of the directory where we kept source code, and we probably wouldn't pick such a long name, but that ability would require additional configuration and complexity in the tool. Typing an extra directory name or two is a small price to pay for the increased simplicity and power.
Limitations
As mentioned above, the go command is not a general-purpose build tool. In particular, it does not have any facility for generating Go source files during a build, although it does provide go
generate
, which can automate the creation of Go files before the build. For more advanced build setups, you may need to write a makefile (or a configuration file for the build tool of your choice) to run whatever tool creates the Go files and then check those generated source files into your repository. This is more work for you, the package author, but it is significantly less work for your users, who can use "go get
" without needing to obtain and build any additional tools.
More information
For more information, read How to Write Go Code and see the go command documentation.
26 About the go command go命令行的更多相关文章
- 安全性测试入门:DVWA系列研究(二):Command Injection命令行注入攻击和防御
本篇继续对于安全性测试话题,结合DVWA进行研习. Command Injection:命令注入攻击. 1. Command Injection命令注入 命令注入是通过在应用中执行宿主操作系统的命令, ...
- C# 动态生成word文档 [C#学习笔记3]关于Main(string[ ] args)中args命令行参数 实现DataTables搜索框查询结果高亮显示 二维码神器QRCoder Asp.net MVC 中 CodeFirst 开发模式实例
C# 动态生成word文档 本文以一个简单的小例子,简述利用C#语言开发word表格相关的知识,仅供学习分享使用,如有不足之处,还请指正. 在工程中引用word的动态库 在项目中,点击项目名称右键-- ...
- [C#学习笔记3]关于Main(string[ ] args)中args命令行参数
Main(string[] args)方法是C#程序的入口,程序从这里开始执行,在这里结束.C#代码逻辑要包含在一个类型(Type)中,游离的.全局的变量或函数是不存在的,这里的类型包括类(class ...
- Delphi的命令行编译命令
Borland出品的Delphi,有着闪电般的编译速度,但是在界面控件使用较多.工程项目较大的时候,编译一个工程仍需要一段时间,打开庞大的Delphi IDE,也需要时间.其实,在一个工程开发结束,调 ...
- Windows命令行command的Shell命令详细解析和语法
CMD命令大全及详细解释和语法 Microsoft Windows XP [版本 5.1.2600] 有关某个命令的详细信息,请键入 HELP 命令名 ASSOC 显示或修改文件扩展名关联. A ...
- Mac系统终端命令行不执行命令 总出现command not found解决方法
配置过安卓开发环境,改过bash_profile这个文件,最后不知怎么的只有cd命令能执行,我猜测可能修改bash_profile文件后没有保存 导致的 保存命令是: source .bas ...
- Qt_Window@Qt Command Prompt从命令行创建工程
#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplicatio ...
- MAC 命令行工具(Command Line Tools)安装
不过升级后安装命令行工具(Command Line Tools)时发现官网没有clt的下载安装包了,原来改了,使用命令在线安装. 打开终端,输入命令:xcode-select --install 选择 ...
- mac下使用命令行打包出现bash gradle command not found的解决方案
命令行打包的时候出现 bash gradle command not found这个问题,主要是因为gradle环境丢失.需要重新配置gradle的环境变量. 1. gradle路径的查找 然后gra ...
随机推荐
- ajax请求提交到controller后总是不成功
最近在做实习时,点击查询时在js中发送ajax请求到controller后台,但是无论怎么样都不成功,请求地址是正确的,因为在后台用system.out.println输出有值,并且也确实return ...
- BZOJ2007 [Noi2010]海拔 【平面图最小割转对偶图最短路】
题目链接 BZOJ2007 题解 这是裸题啊,,要是考试真的遇到就好了 明显是最小割,而且是有来回两个方向 那么原图所有向右的边转为对偶图向下的边 向左的边转为向上 向下转为向左 向上转为向右 然后跑 ...
- linux内核设计与实现一书阅读整理 之第五章
CHAPTER 5 系统调用 5.1 与内核通信 系统调用在用户空间进程和硬件设备之间添加了一个中间层,该层主要作用有三个: 为用户空间提供了一种硬件的抽象接口 系统调用保证了系统的稳定和安全 每个进 ...
- bzoj 1914: [Usaco2010 OPen]Triangle Counting 数三角形
USACO划水中... 题目中要求经过原点的三角形数目,但这种三角形没什么明显的特点并不好求,所以可以求不经过原点的三角形数量. 对于一个非法三角形,它离原点最近的那条边连接的两个点所连的两条边一定在 ...
- 在Struts2的Action中获得request response session几种方法
转载自~ 在Struts2中,从Action中取得request,session的对象进行应用是开发中的必需步骤,那么如何从Action中取得这些对象呢?Struts2为我们提供了四种方式.分别为se ...
- python学习(24) 使用Xpath解析并抓取美女图片
Xpath最初用来处理XML解析,同样适用于HTML文档处理.相比正则表达式更方便一些 Xpath基本规则 nodename 表示选取nodename 节点的所有子节点 / 表示当前节点的直接子节点 ...
- bzoj 1503
1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 12311 Solved: 4399[Submit][Stat ...
- 个人常用Linux文件操作命令
本文只记录个人工作中最常用到的命令. 关机和用户 shutdown -h now 关机 reboot 重启 sync 非正常关机前执行,强制将内存缓冲区中的数据立即写入磁盘中 logout 注销 ...
- 根据Bool值挑选数组中元素
根据Bool值挑选数组中元素 觉得有用的话,欢迎一起讨论相互学习~Follow Me 使用Boolean类型的数组挑选一维数组中的值 使用一维Boolean数组选取数组中的特定元素,对应位置为True ...
- 你知道吗?10个精妙的 Java 编码最佳实践
这是一个比Josh Bloch的Effective Java规则更精妙的10条Java编码实践的列表.和Josh Bloch的列表容易学习并且关注日常情况相比,这个列表将包含涉及API/SPI设计中不 ...