Go系列一
一、语法基础
1、package:声明包。类似Java。Go程序是由包组成的。程序入口的包是main。
2、import:导入包。类似Java。利用圆括号可以导入多个包,或者逐个导入。
3、func:定义函数。
4、导出的名称,首字母是大写。
5、变量类型在变量名后面。
6、函数的命名参数,多个连续同类型,可以只保留最后一个类型。
x int, y int // 简写成: x, y int
7、函数返回值位于函数签名的尾部。
8、函数返回值可以有名字,并且像变量一样使用。
9、return语句没有参数,即返回各个变量的当前值。
10、:=,短声明变量,明确类型的赋值语句,只能用在函数内。
11、基本类型:bool,string,int,int8,int16,int32,int64,uint8,uint16,uint32,uint64,uintptr,byte,rune,float32,float64,complex64,complex128。
12、var可以利用圆括号包含多个变量声明。
13、没有初始化的变量,会被赋值为零值。类似C/C++中的默认值。数值类型为0,布尔类型为false,字符串类型为"",指针类型为nil,slice为nil,map为nil。
14、不同类型之间的转换,需要显式指定。C/C++支持隐式类型转换。
15、类型推导:如果右值有明确类型,而左值没有,则左值的类型由右值推导得出。
16、常量(const)不能使用:=。
17、只有for循环,并且没有圆括号,还可以在没表达式时省略分号。没有while循环。
// 死循环
for {
}
18、if条件语句没有圆括号。条件表达式前面可以有语句,并且语句中的变量可以在if和else中使用。
19、switch条件语句没有圆括号。条件表达式前面可以有语句。没有条件表达式,则等价于true。从上到下执行,直到匹配成功。
20、defer:延迟函数调用。类似Objective-C的dispatch_async。defer函数会被压栈。
21、指针不能运算。跟C/C++不同。
var p * int
22、结构体,利用点号访问字段。结构体指针也是用点号访问字段。
type DefaultCreator struct {
clientSet *kubernetes.Clientset
}
23、结构体文法,通过字段值列表来创建一个结构体,键值对可以只列出部分字段。
type Vertex struct {
X, Y int
}
var (
v1 = Vertex{1, 2} // 类型为 Vertex
v2 = Vertex{X: 1} // Y:0 被省略
v3 = Vertex{} // X:0 和 Y:0
p = &Vertex{1, 2} // 类型为 *Vertex
)
24、数组,长度是类型的一部分,不能改变。
var a [2]string a[0] = "Hello" a[1] = "World" fmt.Println(a[0], a[1]) fmt.Println(a)
25、slice(切片),用make函数创建,用append函数添加元素。
// 序列
p := []int{2, 3, 5, 7, 11, 13}
len(p)
p[low:high] // 从下标low到high-1,省略low表示0,省略high表示len(p)
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
// 如果s太小,会分配更大的数组 func append(s []T, vs ...T) []T
26、for循环可以用range遍历slice和map。类似Python。
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
for i, v := range pow {
}
27、range遍历可以使用下划线忽略key(slice的下标)和value。
for _, val := range pow {
}
28、map,用make函数创建。
type Vertex struct {
Lat, Long float64
}
var m map[string]Vertex // 不能添加元素
m = make(map[string]Vertex) // 用make才能添加元素
m["Bell Labs"] = Vertex{
40.68433, -74.39967,
}
29、map文法。类似结构体文法,不过有键。
type Vertex struct {
Lat, Long float64
}
var m = map[string]Vertex{
"Bell Labs": Vertex{
40.68433, -74.39967,
},
"Google": Vertex{
37.42202, -122.08408,
},
}
var m = map[string]Vertex{
"Bell Labs": {40.68433, -74.39967},
"Google": {37.42202, -122.08408},
}
delete(m, "Google") // 删除键值对 v, ok := m["Answer"] // 检查是否包含键值对
30、函数也是值。类似C/C++函数指针。
hypot := func(x, y float64) float64 {
return math.Sqrt(x*x + y*y)
}
hypot(3, 4)
31、闭包
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
pos, neg := adder(), adder()
for i := 0; i < 10; i++ {
pos(i)
neg(-2*i)
}
32、方法:没有类。包内任意数据类型都可以定义任意方法。但是其他包和基础数据类型不行。
type Vertex struct {
X, Y float64
}
// Abs方法接收器是Vertex结构体的指针,即方法属于哪个数据类型
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
v := &Vertex{3, 4}
// 方法接收器通过点号访问方法
v.Abs()
33、方法接收器是指针:1、可以避免方法调用时值拷贝;2、可以修改接收器。
34、接口类型是一组方法的集合。接口类型的值可以是实现接口方法的任何类型。
type Abser interface {
Abs() float64
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
var a Abser
v := Vertex{3, 4}
a = &v
35、隐式接口。
36、fmt包中的Stringer接口,error接口。io包中的Reader接口。image包。
type Stringer interface {
String() string
}
// nil表示成功
type error interface {
Error() string
}
37、http包,实现Handler接口来响应http请求。
package http
type Handler interface {
ServeHTTP(w ResponseWriter, r *Request)
}
38、goroutine,轻量级线程。其实就是协程。共享进程的地址空间。
go f(x, y, z) // 创建一个新的goroutine来运行f函数。
39、channel,有类型的管道。类似C/C++中的pipe。
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // 将和送入 c
}
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // 从 c 中获取
// 缓冲channel,100是缓冲的长度,缓冲满时,发送阻塞;缓冲空时,接收阻塞。 ch := make(chan int, 100)
40、for i := range ch循环会不断从channel接收值,直到channel被发送方关闭。
v, ok := <-ch // 检查channel是否关闭
41、select,可以让一个goroutine在多个通信操作上阻塞等待,默认是default分支,语法很像switch。其实就是Linux内核中select的功能。
func fibonacci(c, quit chan int) {
x, y := 0, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
fibonacci(c, quit)
42、指针也是利用点号来访问。
二、项目开发
1、使用go命令行工具,需要按照固定目录结构来组织代码。因为它是为了维护公共代码库(例如github)中的开源代码而设计的。
2、GOPATH环境变量,指定工作目录。不能跟Go的安装目录相同。工作目录的bin子目录要添加到PATH环境变量中。
export PATH=$PATH:$GOPATH/bin
3、工作目录包含3个子目录:bin(可执行命令),pkg(包对象),src(源文件,按包组织,每个目录一个包)。
bin/ streak # 可执行命令 todo # 可执行命令 pkg/ linux_amd64/ code.google.com/p/goauth2/ oauth.a # 包对象 github.com/nf/todo/ task.a # 包对象 src/ code.google.com/p/goauth2/ .hg/ # mercurial 代码库元数据 oauth/ oauth.go # 包源码 oauth_test.go # 测试源码 github.com/nf/ streak/ .git/ # git 代码库元数据 oauth.go # 命令源码 streak.go # 命令源码 todo/ .git/ # git 代码库元数据 task/ task.go # 包源码 todo.go # 命令源码
4、包路径,可以是任意的唯一路径。
// 比较好的规范。基本路径 $GOPATH/src/github.com/yangwenhuan
5、构建并安装。构建好的二进制,默认安装在bin目录下。
// helloworld目录下有helloworld.go。 // 可以在任意路径执行这个命令,go命令行工具会根据GOPATH 到github.com/yangwenhuan/helloworld路径下查找源文件。 // 如果在helloworld目录下,直接执行go install即可。 go install github.com/yangwenhuan/helloworld

浙公网安备 33010602011771号