03 July 2018
1.每个代码文件都以package 关键字开头,随后跟着包的名字。标准库中的包,只需要给出包名,编译器会自动到GOROOT和GOPATH环境变量所在位置去查找。

2.在Go语言里,标识符要么从包里公开,要么不从包里公开。当代码导入了一个包时,程序可以直接访问这个包中任意一个公开的标识符。这些标识符以大写字母开头。以小写字母开头的标识符是不公开的,不能被其他包中的代码直接访问。

3.在Go语言中,所有变量都被初始化为其零值。对于数值类型,零值是0;对于字符串类型,零值是空字符串;对于布尔类型,零值是false;对于指针,零值是nil。对于引用类型来说,所引用的底层数据结构会被初始化为对应的零值。但是被声明为其零值的引用类型的变量,会返回nil 作为其值。

函数

Go语言使用关键字func声明函数,关键字后面紧跟着函数名、参数以及返回值。

变量声明运算符(:=)。这个运算符用于声明一个变量,同时给这个变量赋值。这个运算符声明的变量和其他使用关键字var 声明的变量没有任何区别。

在Go语言中,通道(channel)和映射(map)与切片(slice)一样,也是引用类型,不过通道本身实现的是一组带类型的值,这组值用于在goroutine之间传递数据。

指针变量可以方便地在函数之间共享数据。使用指针变量可以让函数访问并修改一个变量的状态,而这个变量可以在其他函数甚至是其他goroutine 的作用域里声明。

Go语言支持闭包,函数可以直接访问到那些没有作为参数传入的变量。匿名函数并没有拿到这些变量的副本,而是直接访问外层函数作用域中声明的这些变量本身。

关键字 defer 会安排随后的函数调用在函数返回时才执行。defer可以保证函数一定会被调用。哪怕函数意外崩溃终止,也能保证关键字defer安排调用的函数会被执行。

interface关键字声明了一个接口,这个接口声明了结构类型或者具名类型需要实现的行为。一个接口的行为最终由在这个接口类型中声明的方法决定。

如果声明函数的时候带有接收者,则意味着声明了一个方法。这个方法会和指定的接收者的类型绑在一起。

值类型与指针类型的不同

    //申明一个方法,指定defaultMatcher类型的值作为接收者
    func (m defaultMatcher) Search (feed *Feed, searchTerm string)
    //申明一个方法,指定defaultMatcher类型的指针作为接收者
    func (m *defaultMatcher) Search (feed *Feed, searchTerm string)

两者区别:

使用指针作为接收者声明的方法,只能在接口类型的值是一个指针的时候被调用。使用值作为接收者声明的方法,在接口类型的值为值或者指针时,都可以被调用。

数组使用

数组是一个长度固定的数据类型,用于存储一段具有相同的类型的元素的连续块。数组存储的类型可以是内置类型,如整型或者字符串,也可以是某种结构类型。

声明和初始化数组

var arr [5]int    //初始化为零值
arr := [5]int{1,2,3,4,5}    //初始化并赋值
arr := [...]int{1,2,3,4,5}  //容量由初始化值决定
arr := [5]int{1:10,2:20}  //指定某个值


切片的实现和使用

申明和初始化切片

arr := []int   //空切片
var arr make([]string, 5)  //切片的长度和容量为5
arr := make([]string, 5, 6)   //切片长度为5,容量为6

ps1:不管是使用 nil 切片还是空切片,对其调用内置函数append、len 和cap 的效果都是一样的。

ps2:切片的容量不能小于切片长度。切片和数组区别在于,数组固定长度,切片不固定长度。

使用切片创建切片

slice := []int{10, 20, 30, 40, 50}
newSlice := slice[1:3]
newSlice = append(newSlice,90)
len := len(newSlice)  // len=2
cap := cap(newSlice)  // cap=4 

otherSlice := slice[2:3:4]
len := len(otherSlice)  // len=1
cap := cap(otherSlice)  // cap=2 

函数append 会智能地处理底层数组的容量增长。在切片的容量小于1000 个元素时,总是会成倍地增加容量。一旦元素个数超过1000,容量的增长因子会设为1.25,也就是会每次增加25%的容量。


映射

映射是一个存储键值对的无序集合。之所以是无序的,因为映射的底层实现是用的散列表。

创建和初始化映射

//make初始化
dict := make(map[string]int)
//字面量初始化
dict := map[string]string{"red":"#ffffff","black":"#000000"}

//使用切片作为map的值
dict := map[int][]string{}

映射的使用

colors := map[string]string{"red": "#ffffff", "blue": "#cccccc"}
value, isTure := colors["red"]
if isTure {
    fmt.Printf("val1:%s\n", value)
}

val := colors["blue"]
if val != "" {
    fmt.Printf("val2:%s \n", val)
}

delete(colors, "red")   //从map中删除某个key