基础知识

GOPATH GOROOT

GOROOT是go的安装路径
GOPATH是作为编译后二进制的存放目的地和import包时的搜索路径
GOPATH之下主要包含三个目录: bin、pkg、src,bin目录主要存放可执行文件; pkg目录存放编译好的库文件, 主要是*.a文件; src目录下主要存放go的源文件

import的时候会从GOPATH/src 和GOROOT/src下寻找,GOPATH可以是多个,每个之间由:隔开

go build和go install区别

go build 会生成可实行文件放在当前目录中
go install 则会把它放到 GOPATH/pkg
go install 还会把导入的依赖包编译到 $GOPATH/pkg,并缓存,如果包未做更改,下次编译则直接使用缓存

go的调度

goroutine是go语言的核心设计,它的本质是协程,是实现并行计算的核心。
协程拥有自己的寄存器上下文和栈,切换时将寄存器上下文和栈保存到其他地方,但是与进程和线程的区别在于线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作执行者则是用户自身程序,goroutine也是协程。
goroutine实现依赖于GPM调度模型
G代表goroutine P代表处理器,一般代表CPU核数,由GOMAXPROCS设置,M代表线程


image.png

其中P维护着goroutine队列,G切换时,只是M从G1切到G2而已,都是在用户态进行着,非常轻量
P的本地队列中缺少G时,会从其他P的队列里“偷”一些或者从全局队列里取。
如果G阻塞,则直接切换G即可;如果M阻塞,例如文件IO等阻塞的系统调用,M和G一起,会解除与P的绑定。如果P的本地队列还有其他G,就会绑定另外一个空闲的M,如果没有,则新建一个M,然后继续执行可以执行的G。而之前阻塞的M在返回后,将从别的M中抢占一个P,如果没有成功,则将该M的G放入全局的goroutine队列。


image.png

相同结构体的对象可以互相比较,不同结构体的对象不可以比较

defer语句

1.defer语句后面必须是函数调用,不能是语句,例如defer foo()
2.defer语句执行的函数在本函数执行完毕后执行
3.每次defer语句执行的时候,会把函数“压栈”,函数参数会被拷贝下来,在return前会按照出栈顺序执行这些函数,而执行这些函数的参数值可以是defer时的值,也可以是执行函数时的值,这主要看defer的是一个闭包还是一个函参传递,如果是函参传递,则值确定好了,如果是一个闭包则使用外部值,即最后确定的外部值。
4.return 最先给返回值赋值;接着 defer 开始执行一些收尾工作;最后 RET 指令携带返回值退出函数

defer与panic

defer与panic的执行顺序:如果没有recover住,则先执行defer最后抛出异常的时候打印panic的内容

[]byte和[]rune类型的值可以被显式地直接转换成字符串,反之亦然

make和new的区别

new 它只接受一个参数,这个参数是一个类型,同时分配的内存置位0
make也是用于内存分配的,它只用于chan、map以及切片的内存创建,而且它返回的类型就是这三个类型本身而并不是指针,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

init函数和main函数

相同:这两个函数都是不接收任何参数的,go自动调用。
不同:
1.init函数可以在package中定义多个,且可以在任何package中,main只能在main的package中
调用顺序:同一个文件中的init函数从上到下调用;同一个package按照文件的字典序调用;不同package如果不相互依赖按照import的顺序,如果依赖则按照最先被依赖的package;最后调用main函数

组合和匿名组合

结构体可以嵌套,当一个结构体中包含另一个结构体,这就是组合。

type test1 struct {
    a int
    b int
}
ype test2 struct {
    tt test1
}

而匿名组合就是

type test1 struct {
    a int
    b int
}
ype test2 struct {
    test1
}

匿名组合其实就实现了继承这一特性,我们可以直接在test2调用test1的函数。
如果匿名组合的是指针,那么在定义一个新的test2的时候需要传入一个test1类型的对象。

你可能感兴趣的:(基础知识)