- sync.Once
- 有在项目中使用过吗?
- viper配置包。第三方配置包,初始化的时候全局初始化只初始化一次,然后就用这个了
- 它是怎么保证只初始化一次?
- sync.once结构体成员有两个:done uint32、m Mutex
- 通过锁和原子操作atomic,done==0就执行函数,反之不执行
- sync.pool
- 有使用过吗?
- 没有
- 声明变量、常量
- 变量:var 、 :=
- 常量:const
- 数组 切片 子切片?
- 数组和切片有什么区别?
- 数组
- 固定长度
- 特定类型元素组成的序列,索引下标取值
- 值类型
- 切片
- 长度不固定,可扩容
- 特定类型元素组成的序列,索引下标取值
- 引用类型
- 数组
- 不同大小的数组,他们可以互相比较吗?
- 不可以,因为是不同的类型。
- 数组可以判断相等和不相等吗?
- 它的长度、类型和数据是一模一样的,就可以不是的话就不可以。
- 切片的内部结构有了解吗?
- 三个成员变量:数组、大小、容量
- 平时有用过子切片吗?
- var a []int{1,2,3} b := a[1:3]
- b里面有几个值?
- 2个,左闭右开,3是取不到的,只能取到索引下边1和2的元素
- 假设b[0] = 100,会影响到a吗?
- 会,因为切片是引用类型,b是a的子切片,它们共用一个数组
- 切片的扩容机制有了解吗?
- 1、slice长度小于1024时,每次扩容后的容量翻倍。比如初始化容量为4的切片,扩容后切片的容量将变为8
- 2、slice长度大于1024时,每次扩容后的容量将会增加25%,比如初始化容量为1024,当添加1025个元素时,容量将变为1280
- make
- 一般是给什么类型使用?
- slice、map、channel
- 给slice用是接收几个参数
- 3个 数组、大小、容量
- new和make
- 区别?
- new
- 分配的空间被清零(零值)
- new 主要用于值类型数据
- 返回该类型零值的指针
- make
- 分配空间后,会进行初始化
- 主要用于slice、map、channel
- 返回类型本身
- new
- new用在slice、map、channel会发生什么?
- 对于slice、map、channel使用new会返回指针,但是不会初始化对应的内存
- new和var区别是什么?
- var用于声明变量并分配零值
- new用于为值类型分配内存并返回指向新分配的零值的指针。
- var a *int 过程是怎么样?会分配内存吗?
- 变量a是一个指向整数类型的指针变量。当你声明一个指针变量时,Go语言会为该变量分配内存空间来存储指针的值,但不会为指针变量所指向的数据分配内存空间
- map
- map的了解是什么?
- 无序的(我们无法决定它的返回顺序,这是因为 map 是使用 hash 表来实现的),键值对,并发不安全,引用类型
- key的类型有什么限制吗?
- 能够比较的类型,slice、func、map不行,结构体下面有slice也不行
- 有什么方法让map并发安全
- 加锁,读写锁、互斥锁
- sync.map
- sync.map和map的使用有什么区别?
- 操作是通过load(获取) store(存储) delete(删除) range(循环)
- defer
- 是干什么用的?
- 注册延迟调用,多个defer执行循序是先进后出。一个函数里面也可以有多个defer,一般用来关闭文件句柄、锁资源释放、recover 捕获错误,异常处理
- 多个defer执行循序
- 先进后出
- return的机制你有了解过吗?它是一个原子性的操作吗?
- 先计算返回值,再返回
- 和defer结合起来就是:先计算返回值,执行defer,再返回
- 不是原子性,定义具名返回值,在defer里面做修改,返回值会被修改
- panic
- panic是什么
- 异常
- 怎么捕获panic
- 通过defer里面,使用recover。defer需要在异常前面定义
- 实际项目当中对异常的捕获怎么做?
- 定义一个捕获异常函数,在每个协程开头调用这个函数
- 通过go关键字起一个携程,要是在开头忘记捕获异常了,项目中有没有对应的一些措施来保证
- 比如说我可以定义一个方法,比如说GoSafe(f func)他接收一个,他接受一个函数类型什么的,在这个里面再去用够关键字。
- 项目中怎么做error错误处理的?
- 一般,基本上每个方法都有返回error,然后从底层如果判断有error的话,就一直返回,返回到顶层,有个统一处理的地方
- 指针
- 在内存中开辟了一片空间,空间存放着一个值(10),这片空间在整个内存当中,有一个唯一的地址,用来进行标识,指向这个地址的变量就称为指针
- 指针可以进行加减法操作吗?
- 不可以指针是不能运算跟偏移的。
- 值类型和引用类型有哪些:
- 值类型:int、float、bool、string、数组、struct
- 引用类型:slice、map、channel、指针、func、interface
- 值类型和引用类型的区别是什么?
- 值类型如果进行数据传递的话,就会发生数据拷贝。如果引用类型进行参数传递的话,就是只拷贝它的地址不会拷贝底层数据
- 引用类型进行参数传递,在函数里面修改值,会影响到外面吗?
- 会
- 如果是有一个函数。他会接收一个切片。如果我在函数内部,进行append操作,那么会影响到原切片吗?
- 如果发生扩容,就不会影响原切片,它底层会变成一个新的数组了。没发生扩容就会影响到原切片
- 内存逃逸有了解吗?
- 变量类型不确定,必定分配到堆(heap)
- 变量作用域,超出了函数体,必定分配到堆
- 变量太大,优先分配到堆
- 变量大小不确定,必定分配到堆
- 为什么从栈上逃逸到堆上?
- 因为他在其他地方有引用,如果不逃逸进去,马上清除了的话,就会发生对象丢失 - 栈和堆的性能对比?
- 栈快,栈上没有锁,堆上有锁 - 逃逸分析指令是什么?
- go build -gcflags ‘-m -m -l’ - 有没有做过逃逸分析和相应的优化?
- - goroutine
- 通过关键词 go,在调用函数的时候在前面加上go关键字,就可以为一个函数创建一个goroutine
- 当main()函数结束了,所有在main()函数中启动的goroutine会一同结束
- goroutine的调度是随机的
- 一个goroutine的栈在其生命周期开始时只有很小的栈(典型情况下2KB),goroutine的栈不是固定的,他可以按需增大和缩小,goroutine的栈大小限制可以达到1GB
- 项目中是怎么使用?
- 通过go关键是起一个携程去进行异步处理一些无关的一些不影响主流程业务的代码 - 怎么进行gorouting编排?
- sync.waitgroup
- channel
- go语言的并发是CSP模型(并发编程模型),通过通信同享内存,而不是通过共享内存而实现通信
- channel是一种类型,一种引用类型
- 通过make函数初始化
- 操作 发送(send) 接收(receive) <-ch 关闭(close)
- 关闭后的通道有以下特点
- 对一个关闭的通道再发送值就会发生panic
- 对一个关闭的通道进行接收会一直获取值直到通道为空
- 对一个关闭的并且没有值的通道执行接收操作会得到对应类型的零值
- 关闭一个已经关闭的通道会导致panic
- 无缓冲通道:无缓冲的通道又称为阻塞的通道,使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称为同步通道。
- 有缓冲通道:通道的容量填满才会阻塞,使用内置的len函数获取通道内元素的数量,使用cap函数获取通道的容量
- 单向通道:函数中只能发送或只能接收
- channel种类?
- 无缓冲通道:无缓冲的通道又称为阻塞的通道,使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称为同步通道。
- 有缓冲通道:通道的容量填满才会阻塞,使用内置的len函数获取通道内元素的数量,使用cap函数获取通道的容量 - 有没有遇到过channel一直阻塞的情况?
- 接收方或者发送方没有正常执行 - 一直阻塞会导致什么问题?
- 一直阻塞如果是在gorouting里面,gorouting就不会释放,也不会被垃圾回收,导致内存泄漏 - 有方向的channel?
- 单向通道:函数中只能发送或只能接收 - 有方向channel在项目中主要是为了干什么
- 防止误操作