知识点
1.Go是一个快速的、静态类型的编译型语言,感觉却像动态类型的解释型语言(所以还是编译型语言)
2.Less can be more(少即是多)
3.并发编程方面Golang使用一种称为goroutine的协程作为并发执行单元
4.协程又称微线程,比线程更轻量、开销更小,性能更高,一个线程可以包含多个协程,共享堆不共享栈
5.Golang中实现协程通讯有两种类型,分别是1)共享内存型,即使用全局变量+mutex锁来实现数据共享;2)消息传递型,即使用一种独有的channel机制进行异步通讯。高并发是Golang语言最大的亮点
6.程序在内存上被分为堆区、栈区、全局数据区、代码段、数据区五个部分。 Go 中栈上内存仍和C++等早期语言类似由编译器负责管理回收,而堆上的内存由编译器和垃圾收集器负责管理回收,给编程人员带来了极大的便利性。
7.Go1.3的GC机制是标记清除法,先STW(stop the world),扫描内存,把可回收对象在一段bitmap区中标记下来,接着结束STW,恢复服务,同时起一个专门gorountine回收内存到空闲list中以备复用,不物理释放。物理释放由专门线程定期来执行。循环该过程直到 main 生命周期结束。
8.最初是将垃圾清理结束时才停止 STW,后来优化了方案将清理垃圾放到了 STW 之后,与程序运行同时进行,这样做减小了 STW 的时长。因为STW会暂停用户程序,对性能影响极大,所以Go1.5 采用了三色标记法优化了 STW。具体请参考https://learnku.com/articles/59021
9.目前Golang具有两种编译器,一种是建立在GCC基础上的Gccgo,另外一种是分别针对64位x64和32位x86计算机的一套编译器(6g和8g)。
10.Golang是强类型语言。(支持一些语法糖,自动推导)
11.go install 和 go build需要目录下只有一个命令源码文件,go run可以单独执行任一命令源码文件
12.go build 命令主要是用于测试编译。在包的编译过程中,若有必要,会同时编译与之相关联的包
13.如果是普通包,当你执行go build命令后,不会产生任何文件
14.如果是main包,当只执行go build命令后,会在当前目录下生成一个可执行文件。如果需要在$GOPATH/bin目录下生成相应的exe文件,需要执行go install 或者使用 go build -o 路径/可执行文件
15.如果某个文件夹下有多个文件,而你只想编译其中某一个文件,可以在 go build 之后加上文件名,例如 go build a.go;go build 命令默认会编译当前目录下的所有go文件
16.你也可以指定编译输出的文件名。比如,我们可以指定go build -o 可执行文件名,默认情况是你的package名(非main包),或者是第一个源文件的文件名(main包)
17.go build 会忽略目录下以””或者”.”开头的go文件
18.如果使用 go install 命令,如果 GOPATH 里面只有一个工作区,就会在当前工作区的 bin 目录下生成相应的可执行文件
19.如果 GOPATH 下有多个工作区,则是在 GOBIN 下生成对应的可执行文件
20.go run、go install以及go build具体干了啥请参考https://github.com/sher1096/Golang-100-Days/blob/master/Day01-15(Go%E8%AF%AD%E8%A8%80%E5%9F%BA%E7%A1%80)/day01%E7%AC%AC9%E8%8A%82_Go%E7%9A%84%E5%91%BD%E4%BB%A4%E4%BB%A5%E5%8F%8AGo%E7%9A%84%E6%89%A7%E8%A1%8C%E5%8E%9F%E7%90%86.md
21.需要注意变量定义了就要使用,否则无法通过编译
22.Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch, 但是可以使用fallthrough强制执行后面的case代码
23.变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。 您可以同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3
24.如需贯通后续的case,就添加fallthrough,fallthrough应该是某个case的最后一行。如果它出现在中间的某个地方,编译器就会抛出错误
25.可以用switch判断变量类型
package main
import "fmt"
func main() {
var x interface{}
switch i := x.(type) {
case nil:
fmt.Printf(" x 的类型 :%T",i)
case int:
fmt.Printf("x 是 int 型")
case float64:
fmt.Printf("x 是 float64 型")
case func(int) float64:
fmt.Printf("x 是 func(int) 型")
case bool, string:
fmt.Printf("x 是 bool 或 string 型" )
default:
fmt.Printf("未知型")
}
}
26.循环只有for循环, 格式为
for init; condition; post { }
27.可以用for遍历数组,map等
for key, value := range oldMap {
newMap[key] = value
}
28.你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回
29.当外围函数中的语句正常执行完毕时,只有其中所有的延迟函数都执行完毕,外围函数才会真正的结束执行
30.当执行外围函数中的return语句时,只有其中所有的延迟函数都执行完毕后,外围函数才会真正返回
31.当外围函数中的代码引发运行恐慌时,只有其中所有的延迟函数都执行完毕后,该运行时恐慌才会真正被扩展至调用函数
32.Go 语言的入口 main() 函数所在的包(package)叫 main,main 包想要引用别的代码,需要import导入
33.需要详细了解init和main的区别https://github.com/sher1096/Golang-100-Days/blob/master/Day01-15(Go%E8%AF%AD%E8%A8%80%E5%9F%BA%E7%A1%80)/day11_%E5%8C%85%E7%9A%84%E7%AE%A1%E7%90%86.md#5init-%E5%8C%85%E5%88%9D%E5%A7%8B%E5%8C%96