最近新的工作一些代码是go语言写的,学了一些go语言的基本语法。后期有一些别的学习总结,在此文档更新。
1语法
1.1变量/常量定义
var v Type
var v Type = value
var v = value
var v1,v2,v3 Type
var v1,v2,v3 Type = value1,value2,value3
var v1,v2,v3= value1,value2,value3
v1,v2,v3:= value1,value2,value3
i,j = j,i
:=为简短声明,编译器根据初始化的值自动推断相应的类型,但是不能定义在函数外部使用。
const(
s = “string”
pi = 3.1415
pi2
)
var(
i int
pi float32 = 3.1415
)
1.2 array & slice
array定义
var a [2]int = [2]int{1,2}
a := [2]int{1,2}
a := [...]int{1,2,3,4}
a2 := [2][3]int{[3]int{1,2,3},[3]int{3,2,1}}
a2 := [2][3]int{{1,2,3},{3,2,1}}
slice定义
slice是引用类型
var s []int = make([]int,n)
s := []int{v1,v2,v3}
1.3 map
var m map[keyType]valueType //keyType可以是string及完全定义了==/!=操作的类型
m := make(map[keyType]valueType)
m:=map[keyType]valueType{k1:v1,k2:v2,k3:v3}
len(m map[keyType]valueType)int
delete(m map[Type]Type1,key Type)
1.4 if语句
a)条件语句不需要使用括号将条件括起来;
b)无论语句体有几条语句,花括号{}都是必须存在的;
c)左花括号{ 必须与if或者else在同一行;
d)在if之后,条件语句之前,可以添加变量初始化语句,用;间隔;
e)在有返回值的函数中,不允许将“最终的”return语句包含在if...else...中,否则会编译错误。
1.5 go语句
go fmt.Println("Go!") go语句仅由一个关键字go和一条表达式语句构成。
go语句的执行与其携带的表达式语句的执行在时间上没有必然联系。这里能够确定的仅仅是后者会在前者完成之后发生。在go语句被执行时,其携带的函数(也被称为go函数)以及要传给它的若干参数(如果有的话)会被封装成一个实体(即Goroutine),并被放入到相应的待运行队列中。Go语言的运行时系统会适时的从队列中取出待运行的Goroutine并执行相应的函数调用操作。注意,对传递给这里的函数的那些参数的求值会在go语句被执行时进行。这一点也是与defer语句类似的。
一句话就是go 语句就是起一个线程。
1.6 select 语句
select是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。select随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的。
以下描述了 select 语句的语法:
(1)每个case都必须是一个通信
(2)所有channel表达式都会被求值
(3)所有被发送的表达式都会被求值
(4)如果任意某个通信可以进行,它就执行;其他被忽略。
(5)如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。
否则:
如果有default子句,则执行该语句。
如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel 或值进行求值。
1.7 nil解释
(1)nil并不是Go的关键字之一,nil的意思是无,或者是零值。在Go语言中,如果你声明了一个变量但是没有对它进行赋值操作,那么这个变量就会有一个类型的默认零值。这是每种类型对应的零值:
bool -> false
numbers -> 0
string -> ""
pointers -> nil
slices -> nil
maps -> nil
channels -> nil
functions -> nil
interfaces -> nil
(2)对于指针对象的方法来说,就算指针的值为nil
也是可以调用的;
(3)一个为nil的slice,除了不能索引外,其他的操作都是可以的,当你需要填充值的时候可以使用append函数,slice会自动进行扩充。
// nil slices
var s []slice
len(s) // 0
cap(s) // 0
for range s // iterates zero times
s[i] // panic: index out of range
(4)对于nil的map,我们可以简单把它看成是一个只读的map,不能进行写操作,否则就会panic。
// nil maps
var m map[t]u
len(m) // 0
for range m // iterates zero times
v, ok := m[i] // zero(u), false
m[i] = x // panic: assignment to entry in nil map
(5)关闭一个nil的channel会导致程序panic。+
(6)interface并不是一个指针,它的底层实现由两部分组成,一个是类型,一个值,也就是类似于:(Type, Value)。只有当类型和值都是nil的时候,才等于nil。
1.8 管道(Channel)
管道是Go语言在语言级别上提供的goroutine间的通讯方式,我们可以使用channel在多个goroutine之间传递消息。channel是进程内的通讯方式,是不支持跨进程通信的,如果需要进程间通讯的话,可以使用Socket等网络方式。
管道是类型相关的,即一个管道只能传递一种类型的值。管道中的数据是先进先出的。
语法:
1 // 声明方式,在此ElemType是指此管道所传递的类型
2 var chanName chan ElemType
3 // 声明一个传递类型为int的管道
4 var ch chan int
5 // 声明一个map,元素是bool型的channel
6 var m map[string] chan bool
7
8 // 定义语法,定义需要使用内置函数make()即可,下面这行代码是声明+定义一个整型管道
9 ch := make(chan int)
10 // 事先定义好管道的size,下面这行代码定义管道的size为100
11 ch := make(chan int, 100)
12
13 // 由管道中读写数据,<-操作符是与最左边的chan优先结合的
14 // 向管道中写入一个数据,在此需要注意:向管道中写入数据通常会导致程序阻塞,直到有
15 // 其他goroutine从这个管道中读取数据
16 ch<- value
17 // 读取数据,注意:如果管道中没有数据,那么从管道中读取数据会导致程序阻塞,直到有数据
18 value := <-ch
19
20 // 单向管道
21 var ch1 chan<- float64 // 只能向里面写入float64的数据,不能读取
22 var ch2 <-chan int // 只能读取int型数据
23
24 // 关闭channel,直接调用close()即可
25 close(ch)
26 // 判断ch是否关闭,判断ok的值,如果是false,则说明已经关闭(关闭的话读取是不会阻塞的)
27 x, ok := <-ch
用法例子:
1 package main
2 import "fmt"
3
4 func print(ch chan int) {
5 fmt.Println("Hello world")
6 ch<- 1
7 }
8
9 func main() {
10 chs := make([]chan int)
11 for i := 0; i < 10; i++ {
12 chs[i] = make(chan int)
13 go print(chs[i])
14 }
15
16 for _, ch := range(chs){
17 <-ch
18 }
19 }