Go
make | new
都是用于分配相应类型的内存空间。
区别:
- make
- 仅支持 slice、map、channel 三种数据类型的内存分配和初始化
- 返回值是所创建类型的本身
分配堆上的内存空间,通过GC回收- new
- 分配内存,内存里存的值是对应类型的零值。
- 返回值是所创建类型的指针引用
分配栈上的内存空间,在函数被调用完毕后自动释放
为什么针对slice, map和chan类型专门定义一个make函数?
- slice, map和chan的底层结构上要求在使用时必须初始化,如果不初始化,那值就是零值,也就是nil
- map如果是nil,是不能往map插入元素的,插入元素会引发panic
- chan如果是nil,往chan发送数据或者从chan接收数据都会阻塞
- 对于nil slice,append会对slice的底层数组做扩容,通过调用mallocgc向Go的内存管理器申请内存空间,再赋值给原来的nil slice
defer
- 执行顺序:栈后进先出
- defer 与 return 谁先谁后:return 之后的语句先执行,defer 后的语句后执行
- 在函数退出之前,因为return会生成一个临时变量,defer可以修改返回值(有名返回值或者函数返回指针)
init()
- 在main函数之前执行
- 执行顺序:import –> const –> var –>init()–>main()
- 按照解析的依赖关系,没有依赖的包最先初始化
- 一个文件可以有多个init()函数
函数间参数传递
- Go语言中函数之间参数的传递, 全部是值传递
- 值类型 传递, 将会重新拷贝一份内容, 传递到函数中
- 指针类型 传递, 会创建一个新的指针, 但是新的指针还是指向原来的内存空间
- 选择值传递还是指针传递
- 不想变量被修改, 选择值传递,想要被修改, 选择指针传递
- 变量特别大,考虑到节约空间, 选择指针传递
_ 下划线
- 用在import:仅让导入的包做初始化,而不使用包中其他功能
- 用在返回值:忽略某个值
- 用在变量:用作类型断言
- 用在函数定义中:省略带名的参数
其他
进程 | 线程 | 协程
-
进程:是操作系统对一个正在运行的程序的一种抽象,是资源分配的基本单位。
-
线程:是轻量级的进程,进程中的实际运作单位,是操作系统调度的基本单位。
-
协程:是用户态的线程,调度完全由用户控制,拥有自己的寄存器上下文和栈。
-
一个程序至少有一个进程,一个进程至少有一个线程
-
进程与线程区别:
- 进程间相互独立互不干扰,线程共享进程的资源,线程之间通信比进程之间通信更方便。
- 进程之间的切换比线程之间的切换开销大。
- 进程让操作系统实现并发性,线程让进程的内部实现并发。
-
线程与协程区别:
- 线程是操作系统提供的,由内核调度,协程是由程序调度。
- 协程是子程序切换不是线程切换
-
多进程使用场景:对资源的管理和保护要求高,不限制开销和效率时
-
多线程使用场景:要求效率高,频繁切换时,资源的保护管理要求不是很高时