1、go语言的自动内存管理机制使得只要还有一个指针引用一个变量,那这个变量就会在内存中得以保留,因此在Go语言函数内部返回指向本地变量的指针是安全的。
2、go语言中访问成员变量的方式只有 . 号(因为->是用于通道的操作符,所以go语言中指针不支持->操作符),并且GO语言足够智能,能够自动解引用,但智能也是有限的,只能解一次引用,指针的指针还得自己动手解引用。
3、go vendor 无法精确的引用外部包进行版本控制,不能指定引用某个特定版本的外部包;只是在开发时,将其拷贝过来,但是一旦外部包升级,vendor下的代码不会跟着升级。另外,vendor下面并没有元文件记录引用包的版本信息,因为引用外部包升级会产生很大的问题,无法评估升级带来的风险;
4、Make只用来创建slice,map,channel。 其中map使用前必须初始化, append可直接动态扩容slice,而map不行。
var m map[string]int = make(map[string]int)
m["one"] = 1 //这样是可以的
var m map[string]int = map[string]int{"two", 2}
m["one"] = 1 //这样也可以;
var m map[string]int
m["one"] = 1 //这样就不行。
5、golang中分为值类型和引用类型
值类型分别有:int系列、float系列、bool、string、数组和结构体
引用类型有:指针、slice切片、管道channel、接口interface、map、函数等
值类型的特点是:变量直接存储值,内存通常在栈中分配
引用类型的特点是:变量存储的是一个地址,这个地址对应的空间里才是真正存储的值,内存通常在堆中分配
6、数组用于函数传参时是值复制
注意:方法或函数调用时,传入参数都是值复制(跟赋值一致),除非是map、slice、channel、指针类型这些特殊类型是引用传递。
x := [3]int{1,2,3}
// 数组在函数中传参是值复制
func(arr [3]int) {
arr[0] = 7
fmt.Println(arr) //prints [7 2 3]
}(x)
fmt.Println(x) //prints [1 2 3] (not ok if you need [7 2 3])
// 使用数组指针实现引用传参
func(arr *[3]int) {
(*arr)[0] = 7
fmt.Println(arr) //prints &[7 2 3]
}(&x)
fmt.Println(x) //prints [7 2 3]
7、在Slice、Array、Map的多行书写最后的逗号不可省略
x := []int{
1,
// 2 //error
3, // ok
}
y := []int {1, 2, 3,} // ok
z := []int {1, 2, 3} // 单行书写,最后一个元素的逗号可省略
8、使用for range迭代map时每次迭代的顺序可能不一样,因为map的迭代是随机的。
9、switch的case默认匹配规则不同于其它语言的是,匹配case条件后默认退出,除非使用fallthrough继续匹配;而其它语言是默认继续匹配,除非使用break退出匹配。
10、go中只有后置自增、后置自减,不存在前置自增、前置自减
11、位运算的非操作是^
(跟异或位运算一样),有别于其它语言的~
12、
程序不等所有goroutine结束就会退出。可通过channel实现主协程(main goroutine)等待所有goroutine完成