数组和切片的区别?
数组是同一种数据类型元素的集合,数组在定义时需要指定长度和元素类型:
例如:[3]int [3]int{1,2,3} [...]int{1,2,3}
如果数组作为函数的参数,实际传递的是一份数组的拷贝,而不是数组的指针,在函数中修改数组元素不会影响到原始数组。
切片更加常用,它是拥有相同元素类型可变长度的序列,基于数组类型做的一层封装,支持自动扩容。
切片是一种引用类型,他有三个属性:指针,长度和容量。
底层源码: type slice struct { array unsafe.Pointer len int//元素数量 cap int//容量 }
函数操作的是切片的引用,会影响原始切片。
## make与new的区别?
他们都是用是用来分配内存的。记住make只能用在slice,map和通道的初始化。make返回引用类型本身。
而new只接受一个参数,分配好内存后返回一个指向该类型内存地址的指针。同时把分配的内存置为0。
## GO是引用传递还是值传递?
go是值传递,没有引用传递。
值传递:实参通过拷贝将自身内容传递给形参。
slice,map,指针在传递的过程中,地址都发生了变化,说明传递是一份拷贝。
slice结构主要三部分,上面源码。当append()时,会使len变大,大于len时进行扩容,扩容原来的一倍。
但是里面的data还是指向原来的底层数组,修改新数组会对原数组影响。
如果进行了扩容,会重新创建底层数组,data指向新的数组,修改新数组不会对原数组影响。
## Goroutine
它是Go中比线程还要轻量级的线程—协程。它是go实现并发的关键,可以并发执行方法和函数。
默认情况下,每个独立的Go应用运行时就创建了一个go协程,main函数就在这个协程中运行,这个协程叫主协程,在主协程又产生一个函数的协程。Go协程会进行协同调度,在main主线程执行完不会把控制权交给函数协程,一旦执行完毕,整个程序就立即终止,调度器再也没有时间给那个函数协程了。可以进行手动阻塞,设置睡眠时间。只有非休眠go协程才会被调用。主协程休眠时间必须大于子协程的睡眠时间才可以。
由于GO独特的Error机制,我们无法像java一样try catch捕获异常,可以使用defer+recover解决。recover仅在延迟函数中有效。
## Defer
defer是go的一种延迟调用机制。他的调用机制和执行顺序相反,和栈里的先进后出一样。defer在return之前执行,在函数退出之前可以修改返回值。
## 反射
利用reflect包,typeof动态的获取输入参数接口类型,如果是空返回nil,valueof获取数据的值,接口为空返回0.
## GC:STW
StoptheWorld,在垃圾回收过程中为了保证正确性,防止内存一直增长等问题需要停止赋值器进一步操作对象图的一段过程,这段过程中,整个用户代码被停止或放缓,STW越长,对用户造成的影响就越大(例如延迟)。
1.8中go引入了混合屏障,写入屏障,直接开始,结束时重新扫描栈;删除屏障需要在GC开始STW扫描堆栈来记录初始化快照,结束时不用STW。
标签:协程,函数,##,传递,数组,go,java From: https://www.cnblogs.com/ybex/p/17556111.html