目录

初识Golang

https://prod-files-secure.s3.us-west-2.amazonaws.com/e06f7215-8a35-4590-b3e9-0d6bff059c72/5d14c0d8-d1d6-4910-8132-44742d92d557/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45FSPPWI6X%2F20250102%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250102T111635Z&X-Amz-Expires=3600&X-Amz-Signature=5e4539421d4807a6843ecfb4521cfd5a293c3bff706b2c738ae0619127b5914a&X-Amz-SignedHeaders=host&x-id=GetObject

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. 什么是微服务?

微服务,又称微服务架构,是一种架构风格,它将应用程序构建为以业务领域为模型的小型自治服务集合。

通俗地说,你必须看到蜜蜂如何通过对齐六角形蜡细胞来构建它们的蜂窝状物。他们最初从使用各种材料的小部分开始,并继续从中构建一个大型蜂箱。这些细胞形成图案,产生坚固的结构,将蜂窝的特定部分固定在一起。 这里,每个细胞独立于另一个细胞,但它也与其他细胞相关。这意味着对一个细胞的损害不会损害其他细胞,因此,蜜蜂可以在不影响完整蜂箱的情况下重建这些细胞。