命令
参数
-a :强制编译相关代码,不论它们的遍野结果是否已是最新的(不管导入的代码包中的代码是否改变,都会重新编译一次)
-n :打印编译过程中所需运行的命令,但不真正执行它们
-p n :并行编译,其中n为并行数量(最好设置为当前机器的逻辑cpu的个数)
-v :列出被编译的代码包的名称 可以 -a -v 连用 列出所有涉及到的代码包的名称
-work :显示编译时创建的临时工作目录的路径,并且不删除它
-x :打印编译过程中所需运行的命令,并且真正的执行它们
go run 命令
运行源码文件
go build 命令
用于编译源码文件或代码包
编译非命令源码文件不会产生任何结果文件
编译命令源码文件会在该命令的执行目录中生成一个可执行文件
执行该命令且不追加任何参数时,它会试图把当前目录作为代码包并编译
执行该命令且以代码包的导入路径作为参数时,该代码包及其依赖会被编译
执行该命令且以若干源码文件作为参数时,只有这些文件会被编译
go install 命令
用于编译并安装代码包或源码文件,安装代码包会在当前工作区的pkg/<平台相关目录>下生成归档文件
安装命令源码文件会在当前工作区的bin目录或$GOBIN目录下生成可执行文件
不带参数:编译当前目录
带目录参数:编译参数目录
带源码文件参数:编译源码文件以及涉及到的代码包和依赖
go get 命令
用于从远程代码仓库中下载并安装代码包
支持:Git、Mercurial(hg)、SVN、Bazaar
-x :展示执行过程
-d :只执行下载动作,不执行安装动作
-fix :在下载代码包后先执行修正动作,而后再进行编译和安装
-u :利用网络来更新已有的代码包以及其依赖
nohup ./proxy &
关键字
用途 | 关键字 |
---|---|
程序声明 | import package |
程序实体声明和定义 | chan const func interfase map struct type var |
程序流程控制 | go select break case continue default defer if else fallthrough for goto range return switch |
const —> 声明常量 var —>声明变量
package main // 代码包声明语句。
import ( // 代码包导入语句。
"fmt" // 导入代码包fmt。
)
// main函数。
func main() {
// 打印函数调用语句。用于打印输出信息。
fmt.Println("Go语言编程实战")
}
变量赋值的三种方法:
var num1 int = 1 //单行赋值
var ( //多行赋值
num1 int = 1
num2 int = 2
)
var num1, num2 int = 2, 3 //平行赋值
语法
数组当中的元素,必须类型相同
类型声明语句由关键字type、类型名称、类型字面量组成
如:type MyNumbers [3]int
当我们表示一个数组类型的值的时候,应该把该类型的类型字面量写在最左边
如:[3]int{1,2,3} var numbers = [3]int{1,2,3}
获取数组的长路用
len(numbers)
切片 表示切片类型的字面量如
[]int []string
- 它不包含代表其长度的信息,与数组不同的是,无法通过切片类型来确定其值的长度。每个切片值都会将数组作为其底层数据结构。我们也把这样的数组称为切片的底层数组。
操作数组值的方法也同样适用于切片值。不过,还有一种操作数组值的方法我们没讲到。这种操作的名称就叫“切片”。实施切片操作的方式就是切片表达式。举例如下:
var numbers3 = [5]int{1, 2, 3, 4, 5}
var slice1 = numbers3[1:4
请注意第二条赋值语句中在“=”右边那个部分。切片表达式一般由字符串、数组或切片的值以及由方括号包裹且由英文冒号“:”分隔的两个正整数组成。这两个正整数分别表示元素下界索引和元素上界索引。在本例中
切片表达式numbers3[1:4]的求值结果为[]int{2, 3, 4}
可见,切片表达式的求值结果相当于以元素下界索引和元素上界索引作为依据从被操作对象上“切下”而形成的新值。注意,被“切下”的部分不包含元素上界索引指向的元素。另外,切片表达式的求值结果会是切片类型的,且其元素类型与被“切片”的值的元素类型一致。实际上,slice1
这个切片值的底层数组正是numbers3
的值。
实际上,我们也可以在一个切片值上实施切片操作。操作的方式与上述无异。请看下面这个例子:
var slice2 = slice1[1:3]
slice2的值为[]int{3, 4}
- 注意,作为切片表达式求值结果的切片值的长度总是为元素上界索引与元素下界索引的差值。
除了长度,切片值以及数组值还有另外一个属性——容量。数组值的容量总是等于其长度。而切片值的容量则往往与其长度不同。请看下图。
如图所示,一个切片值的容量即为它的第一个元素值在其底层数组中的索引值与该数组长度的差值的绝对值。为了获取数组、切片或通道类型的值的容量,我们可以使用内建函数cap
,如:
var capacity2 int = cap(slice2)
最后,要注意,切片类型属于引用类型。它的零值即为nil
,即空值。如果我们只声明一个切片类型的变量而不为它赋值,那么该变量的值将会是nil
。例如,若有这样一个变量:
var slice3 []int
则它的值会是nil
在有些时候,我们还可以在方括号中放入第三个正整数,如下所示:
numbers3[1:4:4]
这第三个正整数被称为容量上界索引。它的意义在于可以把作为结果的切片值的容量设置得更小。换句话说,它可以限制我们通过这个切片值对其底层数组中的更多元素的访问。下面举个例子。让我们先来回顾下在上一节讲到的numbers3
和slice1
。针对它们的赋值语句是这样的:
var numbers3 = [5]int{1, 2, 3, 4, 5}
var slice1 = numbers3[1:4]
这时,变量slice1
的值是[]int{2, 3, 4}
。但是我们可以通过如下操作将其长度延展得与其容量相同:
slice1 = slice1[:cap(slice1)]
通过此操作,变量slice1
的值变为了[]int{2, 3, 4, 5}
,且其长度和容量均为4。现在,numbers3
的值中的索引值在[1,5]
范围内的元素都被体现在了slice1
的值中。这是以numbers3
的值是slice1
的值的底层数组为前提的。这意味着,我们可以轻而易举地通过切片值访问其底层数组中对应索引值更大的更多元素。如果我们编写的函数返回了这样一个切片值,那么得到它的程序很可能会通过这种技巧访问到本不应该暴露给它的元素。这是确确实实是一个安全隐患。
如果我们在切片表达式中加入了第三个索引(即容量上界索引),如:
var slice1 = numbers3[1:4:4]
那么在这之后,无论我们怎样做都无法通过slice1
访问到numbers3
的值中的第五个元素。因为这超出了我们刚刚设定的slice1
的容量。如果我们指定的元素上界索引或容量上界索引超出了被操作对象的容量,那么就会引发一个运行时恐慌(程序异常的一种),而不会有求值结果返回。因此,这是一个有力的访问控制手段。
虽然切片值在上述方面受到了其容量的限制,但是我们却可以通过另外一种手段对其进行不受任何限制地扩展。这需要使用到内建函数append
。append
会对切片值进行扩展并返回一个新的切片值。使用方法如下:
slice1 = append(slice1, 6, 7)
通过上述操作,slice1
的值变为了[]int{2, 3, 4, 6, 7}
。注意,一旦扩展操作超出了被操作的切片值的容量,那么该切片的底层数组就会被自动更换。这也使得通过设定容量上界索引来对其底层数组进行访问控制的方法更加严谨了。
我们要介绍的最后一种操作切片值的方法是“复制”。该操作的实施方法是调用copy
函数。该函数接受两个类型相同的切片值作为参数,并会把第二个参数值中的元素复制到第一个参数值中的相应位置(索引值相同)上。这里有两点需要注意:
- 这种复制遵循最小复制原则,即:被复制的元素的个数总是等于长度较短的那个参数值的长度。
- 与
append
函数不同,copy
函数会直接对其第一个参数值进行修改。 举例如下:
通过上述复制操作,var slice4 = []int{0, 0, 0, 0, 0, 0, 0} copy(slice4, slice1)
slice4
会变为[]int{2, 3, 4, 6, 7, 0, 0}
。