1. 什么是 goroutine?如何停止它?#
- 一个 Goroutine 是一个函数或方法执行同时旁边其他任何够程采用了特殊的
Goroutine 线程。 Goroutine 线程比标准线程更轻量级,大多数 Golang 程序
同时使用数千个 Goroutine。 - 要创建 Goroutine,请 go 在函数声明之前添加关键字。
- 您可以通过向 Goroutine 发送一个信号通道来停止它。 Goroutines 只能在被
告知检查时响应信号,因此您需要在逻辑位置(例如 for 循环顶部)包含检
查。
2. 同步锁有什么特点?作用是什么 ?#
- Go 语言中,不要通过共享内存来通信,而要通过通信来实现内存共享。Go 的 CSP (Communicating Sequential Process) 并发模型,中文可以叫做通信顺序进程,是通过 goroutine 和 channel 来实现的。
- 当一个 Goroutine(协程)获得了 Mutex 后,其他 Goroutine(协程)就只能乖乖的等待,除非该 Goroutine 释放了该 Mutex。 RWMutex 在读锁占用的情况下,会阻止写,但不阻止读 RWMutex。 在写锁占用情况下,会阻止任何其他 Goroutine(无论读和写)进来,整个锁相当于由该 Goroutine 独占同步锁的作用是保证资源在使用时的独有性,不会因为并发而导致数据错乱,保证系统的稳定性。
3. Channel 有什么特点,需要注意什么?#
- 如果给一个 nil 的 channel 发送数据,会造成永远阻塞。
- 如果从一个 nil 的 channel 中接收数据,也会造成永久阻塞。
- 给一个已经关闭的 channel 发送数据, 会引起 panic。
- 从一个已经关闭的 channel 接收数据, 如果缓冲区中为空,则返回一个零
值。
4. GoConvey 是什么?一般用来做什么?#
- go convey 是一个支持 Golang 的单元测试框架。
- goconvey 能够自动监控文件修改并启动测试,并可以将测试结果实时输出到 Web 界面。
- go convey 提供了丰富的断言简化测试用例的编写
5. Go 语言中 make 和 new 的区别?#
- 二者都是用来做内存分配的。
- make 只用于 slice、 map 以及 channel 的初始化, 返回的还是这三个引用类型本身。
- 而 new 用于类型的内存分配, 并且内存对应的值为类型零值, 返回的是指向类型的指
针。
6. Go 语言当中数组和切片的区别是什么?#
- 数组:
- 数组固定长度。数组长度是数组类型的一部分,所以 [3] int 和 [4] int 是两种不同的数组类型数组需要指定大小,不指定也会根据初始化,自动推算出大小,大小不可改变。数组是通过值传递的。
- 切片:
- 切片可以改变长度。切片是轻量级的数据结构,三个属性,指针,长度,容量不需要指定大小切片是地址传递(引用传递)可以通过数组来初始化,也可以通过内置函数 make () 来初始化,初始化的时候 len=cap,然后进行扩容。
7. defer 的作用和特点是什么?#
- defer 的作用是:
- 你只需要在调用普通函数或方法前加上关键字 defer,就完成了 defer 所需要的语法。当 defer 语句被执行时,跟在 defer 后面的函数会被延迟执行。直到包含该 defer 语句的函数执行完毕时,defer 后的函数才会被执行,不论包含 defer 语句的函数是通过 return 正常结束,还是由于 panic 导致的异常结束。你可以在一个函数中执行多条 defer 语句,它们的执行顺序与声明顺序相反。
- defer 的常用场景:
- defer 语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。
- 通过 defer 机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。
- 释放资源的 defer 应该直接跟在请求资源的语句后。
8. WaitGroup 用法?#
一个 WaitGroup 对象可以等待一组协程结束。使用方法是:
- main 协程通过调用 wg.Add (delta int) 设置 worker 协程的个数,然后创建 worker 协程;
- worker 协程执行结束以后,都要调用 wg.Done ();
- main 协程调用 wg.Wait () 且被 block,直到所有 worker 协程全部执行结束后返回。
9. WaitGroup 实现原理?#
- WaitGroup 主要维护了 2 个计数器,一个是请求计数器 v,一个是等待计数器 w,二者组成一个 64bit 的值,请求计数器占高 32bit,等待计数器占低 32bit。
- 每次 Add 执行,请求计数器 v 加 1,Done 方法执行,等待计数器减 1,v 为
0 时通过信号量唤醒 Wait ()。
10. 什么是 sync.Once?#
- Once 可以用来执行且仅仅执行一次动作,常常用于单例对象的初始化场景。
- Once 常常用来初始化单例资源,或者并发访问只需初始化一次的共享资源,或者在测试的时候初始化一次测试资源。
- sync.Once 只暴露了一个方法 Do,你可以多次调用 Do 方法,但是只有第一次调用 Do 方法时 f 参数才会执行,这里的 f 是一个无参数无返回值的函数。
11. 什么操作叫做原子操作?#
原子操作即是进行过程中不能被中断的操作,针对某个值的原子操作在被进行的过程中,CPU 绝不会再去进行其他的针对该值的操作。为了实现这样的严谨性,原子操作仅会由一个独立的 CPU 指令代表和完成。原子操作是无锁的,常常直接通过 CPU 指令直接实现。事实上,其它同步技术的实现常常依赖于原子操作。
12. 原子操作和锁的区别?#
- 原子操作由底层硬件支持,而锁则由操作系统的调度器实现。锁应当用来保护一段逻辑,对于一个变量更新的保护。
- 原子操作通常执行上会更有效率,并且更能利用计算机多核的优势,如果要更新的是一个复合对象,则应当使用 atomic.Value 封装好的实现。
13. 什么是微服务?#
微服务,又称微服务架构,是一种架构风格,它将应用程序构建为以业务领域为模型的小型自治服务集合。
通俗地说,你必须看到蜜蜂如何通过对齐六角形蜡细胞来构建它们的蜂窝状物。他们最初从使用各种材料的小部分开始,并继续从中构建一个大型蜂箱。这些细胞形成图案,产生坚固的结构,将蜂窝的特定部分固定在一起。
这里,每个细胞独立于另一个细胞,但它也与其他细胞相关。这意味着对一个细胞的损害不会损害其他细胞,因此,蜜蜂可以在不影响完整蜂箱的情况下重建这些细胞。