grammer
slice 从一个切片中创建的新切片,两者共享同一个底层数组,如果修改共享部分,另一个切片有感知
func main() {
a1 := []int{1,2,3,4}
a2 := a1[0:1]
a2[0] = 0
fmt.Println(a1)
// [0 2 3 4]
}
go struct 能不能比较
- 因为是强类型语言,所以不同类型的结构不能作比较,但是同一类型的实例值是可以比较的,实例不可以比较,因为是指针类型
defer 执行顺序
func main() {
for i := 0; i < 4; i++ {
defer fmt.Print(i)
}
panic(4)
}
// 3210panic: 4
select 可以用于什么,常用于 gorotine 的完美退出
- golang 的 select 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作
- 每个 case 语句里必须是一个 IO 操作,确切的说,应该是一个面向 channel 的 IO 操作
在 go 语言中,new 和 make 的区别
- new 的作用是初始化一个指向类型的指针(*T)
- new 函数是内建函数,函数定义:func new(Type) *Type
- 使用 new 函数来分配空间。传递给 new 函数的是一个类型,不是一个值。返回值是 指向这个新分配的零值的指针。
- make 的作用是为 slice,map 或 chan 初始化并返回引用(T)。
- make 函数是内建函数,函数定义:func make(Type, size IntegerType) Type
- 第一个参数是一个类型,第二个参数是长度
- 返回值是一个类型
- make(T, args)函数的目的与 new(T)不同。它仅仅用于创建 Slice, Map 和 Channel,并且返回类型是 T(不是 T*)的一个初始化的(不是零值)的实例。
说说 go 语言中,数组与切片的区别
-
数组
- 数组是具有固定长度且拥有零个或者多个相同数据类型元素的序列。
- 数组的长度是数组类型的一部分,所以[3]int 和 [4]int 是两种不同的数组类型。
- 数组需要指定大小,不指定也会根据初始化的自动推算出大小,不可改变 ;
- 数组是值传递;
- 数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从 0 开始的下标索引访问元素值。在初始后长度是固定的,无法修改其长度。当作为方法的参数传入时将复制一份数组而不是引用同一指针。数组的长度也是类型的一部分,通过内置函数 len(array)获取其长度。
- 数组定义:
- var array [10]int
- var array = [5]int{1,2,3,4,5}
-
切片
- 切片表示一个拥有相同类型元素的可变长度的序列。
- 切片是一种轻量级的数据结构,它有三个属性:指针、长度和容量。
- 切片不需要指定大小;
- 切片是地址传递;
- 切片可以通过数组来初始化,也可以通过内置函数 make()初始化 .初始化时 len=cap,在追加元素时如果容量 cap1. 不足时将按 len 的 2 倍扩容;
- 切片定义:var slice []type = make([]type, len)
go 语言中的引用类型包含哪些
- 数组切片、字典(map)、通道(channel)、接口(interface)
go 语言中指针运算有哪些
- 可以通过“&”取指针的地址
- 可以通过“*”取指针指向的数据
说说 go 语言的 channel 特性
- 给一个 nil channel 发送数据,造成 fatal error: all goroutines are asleep - deadlock!
- 从一个 nil channel 接收数据,造成永远阻塞
- 给一个已经关闭的 channel 发送数据,引起 panic
- 从一个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回一个零值
- 无缓冲的 channel 是同步的,而有缓冲的 channel 是非同步的
说说进程、线程、协程之间的区别
- 进程是资源的分配和调度的一个独立单元,而线程是 CPU 调度的基本单元;
- 同一个进程中可以包括多个线程;
- 进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束;
- 线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程;
- 进程的创建调用 fork 或者 vfork,而线程的创建调用 pthread_create;
- 线程中执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源;
- 进程是资源分配的单位,线程是操作系统调度的单位
- 效率
- 进程切换需要的资源很最大,效率很低
- 线程切换需要的资源一般,效率一般
- 协程切换任务资源很小,效率高
- 多进程、多线程根据 cpu 核数不一样可能是并行的 也可能是并发的。协程的本质就是使用当前进程在不同的函数代码中切换执行,可以理解为并行。 协程是一个用户层面的概念,不同协程的模型实现可能是单线程,也可能是多线程。
- 进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。(全局变量保存在堆中,局部变量及函数保存在栈中)
- 线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是这样的)。
- 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。
- 一个应用程序一般对应一个进程,一个进程一般有一个主线程,还有若干个辅助线程,线程之间是平行运行的,在线程里面可以开启协程,让程序在特定的时间内运行。
- 协程和线程的区别是:协程避免了无意义的调度,由此可以提高性能,但也因此,程序员必须自己承担调度的责任,同时,协程也失去了标准线程使用多 CPU 的能力。