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 ...
随机推荐
- 【BZOJ4004】【JLOI2015】装备购买
Description 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 < ...
- 【bzoj3926】 Zjoi2015—诸神眷顾的幻想乡
http://www.lydsy.com/JudgeOnline/problem.php?id=3926 (题目链接) 题意 给出一棵树,每个节点有一个编号,范围在${[0,9]}$.一个序列是指树上 ...
- sqlmap利用DNS进行oob(out of band)注入(转)
0x00 起因 实际案子的时候遇到了一个注入,过狗可以使用sqlmap,但是是基于时间的注入和限制频率需要使用--delay参数,本来就是延时再加上--delay等的心力憔悴.所有有了下面介绍使用 ...
- CAS使用心得
1.理解CAS实现SSO需要哪些组成部分 2.理解CAS实现SSO流程,包括登陆.注销.二次登陆.其他应用登陆 3.CAS部署需要SSL支持,理解容器如何开启SSL.服务端证书.jre证书信任.创建以 ...
- Android Studio自动生成UML关系类图
android studio 根据源码自动生成UML的插件介绍http://www.jianshu.com/p/cbccd831cf01 simpleumlhttps://plugins.jetbra ...
- ButterKnife注入注解框架用法
Android 依赖注入 ButterKnife 基本使用 - 渐行渐远渐无声 - 博客园http://www.cnblogs.com/fansen/p/5653887.html ButterKnif ...
- 【bzoj2938】【Poi2000】病毒
题解: 对病毒串建立ac自动机: 有一个无限长的串等价于可以一直在自动机上匹配,等价于自动机上的转移有环: 当然前提是去掉病毒节点的fail子树: 写一个dfs记录是否在栈中,来过没有找到就不必再来了 ...
- MySQL 第八篇:ORM框架SQLAlchemy
一 介绍 SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数据API执行SQL并获取 ...
- python学习笔记__反射
反射 # 通过字符串的形式对对象中的成员进行操作(获取/查找/添加/删除). 操作的内置函数: 1.获取 getattr(object, name) # 去对象object中获取name的内容 c ...
- ElasticStack系列之十二 & 搜索结果研究
问题 使用 ElasticSearch 做搜索 时,比如用户输入 --> 柠檬,搜出来的结果 --> 柠檬汽水,柠檬味牙膏等在前面,真正想要的水果那个 柠檬 在后面.已经在中文分词中加了 ...