Golang面试手册
薪资15~25k
岗位职责:
- 负责公司自有平台的研发工作包括系统功能模块开发;
- 系统API接口开发等持续优化产品;
- 关注技术细节,并能根据业务需求,提出技术和架构方案;
- 担任重点项目的技术指导并负责底层核心代码的开发;
- 负责技术文档整理,解决项目中的技术难题,关键技术难点攻关;
岗位要求
- 本科及以上学历,计算机、信息科学及相关专业毕业;
- 必须有区块链相关开发经验;
- 三年以上开发经验,具备较强的代码能力,能独立进行Golang程序开发;
- 熟练使用Gin、Beego、Echo或其他常用开发框架全程独立开发过至少一个项目;
- 熟悉Nginx、Redis、MySQL、Kafka,熟悉Linux服务器的管理及常用命令,熟悉系统部署配置,能进行性能分析及解决;
- 具备复杂业务需求梳理能力,较强的分析解决问题能力和产品思维;
- 有大型分布式、大容量、高并发系统设计或金融类开发经验者优先;
- 有Python、Java、PHP语言相关开发经验优先;
- 对代码和设计质量有严格要求,良好的编码习惯和严格的编码规范;
- 高度的责任心、良好的沟通技巧和团队合作精神,主动性和自我驱动意识强,热爱开发事业;
- 基础
- Golang中除了加Mutex锁以外还有哪些方式安全读写共享变量?
Golang中Goroutine 可以通过 Channel 进行安全读写共享变量
- new 和 make 的区别 ?
Go数据类型分为值类型和引用类型,其中值类型是 int、float、string、bool、struct和array,它们直接存储值,分配栈的内存空间,它们被函数调用完之后会释放;引用类型是 slice、map、chan和值类型对应的指针 它们存储是一个地址(或者理解为指针),指针指向内存中真正存储数据的首地址,内存通常在堆分配,通过GC回收。
区别:
-
- new 的参数要求传入一个类型,而不是一个值,它会申请该类型的内存大小空间,并初始化为对应的零值,返回该指向类型空间的一个指针;
- make 也用于内存分配,但它只用于引用对象 slice、map、channel的内存创建,返回的类型是类型本身;
- G olang内存管理 ?
Go语言的内存分配器采用了跟 tcmalloc 库相同的多级缓存分配模型,该模型将引入了线程缓存(Thread Cache)、中心缓存(Central Cache)和页堆(Page Heap)三个组件分级管理内存。
- 如果 goroutine 一直占用资源怎么办,GMP模型怎么解决这个问题 ?
如果有一个goroutine一直占用资源的话,GMP模型会从正常模式转为饥饿模式,通过信号协作强制处理在最前的 goroutine 去分配使用
- 如果若干个线程发生OOM,会发生什么 ? 项目出现过OOM吗,怎么解决 ?
线程如果线程发生OOM,也就是内存溢出,发生OOM的线程会被kill掉,其它线程不受影响
- Goroutine中内存泄漏的发现与排查 。
Go中的内存泄漏一般都是goroutine泄露,就是goroutine没有被关闭,或者没有添加超时控制,让goroutine一只处于阻塞状态,不能被GC。在Go中内存泄露分为暂时性内存泄露和永久性内存泄露。
暂时性内存泄露,string相比切片少了一个容量的cap字段,可以把string当成一个只读的切片类型。获取长string或者切片中的一段内容,由于新生成的对象和老的string或者切片共用一个内存空间,会导致老的string和切片资源暂时得不到释放,造成短暂的内存泄漏。
永久性内存泄露,主要由goroutine永久阻塞而导致泄漏以及time.Ticker未关闭导致泄漏引起。
- Go的垃圾回收算法
Go 现阶段采用的是通过三色标记清除扫法与混合写屏障GC策略。其核心优化思路就是尽量使得 STW(Stop The World) 的时间越来越短
- 线程和协程堆栈的内存大小 ?
线程一般是4M,协程一般是2K
- chan的实现原理 ?
Go的多线程实现采用CSP模型。各个线程独立顺序执行,两个goroutine间表面上没有耦合,而是采用channel作为其通信的媒介,达到线程间同步的目的。 channel 是一个用于同步和通信的有锁FIFO队列;
- Go语言中的并发安全性是什么?如何确保并发安全性?
并发安全性是指在并发编程中,多个goroutine对共享资源的访问不会导致数据竞争和不确定的结果。
为了确保并发安全性,可以采取以下措施:
****使用互斥锁(Mutex):****通过使用互斥锁来保护共享资源的访问,一次只允许一个goroutine访问共享资源,从而避免竞争条件。
****使用原子操作(Atomic Operations):****对于简单的读写操作,可以使用原子操作来保证操作的原子性,避免竞争条件。
****使用通道(Channel):****通过使用通道来进行goroutine之间的通信和同步,避免共享资源的直接访问。
****使用同步机制:****使用同步机制如等待组(WaitGroup)、条件变量(Cond)等来协调多个goroutine的执行顺序和状态。
- Go语言中的defer关键字有什么作用 ?
defer关键字用于延迟函数的执行,即在函数退出前执行某个操作。defer通常用于释放资源、关闭文件、解锁互斥锁等清理操作,以确保在函数执行完毕后进行处理。
也可以使用defer语句结合time包实现函数执行时间的统计。
- Go语言中的指针有什么作用 ?
指针是一种变量,存储了另一个变量的内存地址。通过指针,我们可以直接访问和修改变量的值,而不是对变量进行拷贝。
- Go语言中的map是什么 ?
map是一种无序的键值对集合,也称为字典。map中的键必须是唯一的,而值可以重复。map提供了快速的查找和插入操作,适用于需要根据键快速检索值的场景。
- map是无序的,每次迭代map的顺序可能不同。如果需要按特定顺序遍历map,应该怎么做呢?
在Go语言中,map是无序的,每次迭代map的顺序可能不同。如果需要按特定顺序遍历map,可以采用以下步骤:
- 创建一个切片来保存map的键;
- 遍历map,将键存储到切片中;
- 对切片进行排序;
- 根据排序后的键顺序,遍历map并访问对应的值。
- Go语言中的slice和数组有什么区别?请给出一个使用slice的示例。
在Go语言中,数组和切片(slice)都是用于存储一组相同类型的元素。它们的区别在于长度的固定性和灵活性。数组的长度是固定的,而切片的长度是可变的。
- Go语言中的select语句是什么?请给出一个使用select语句的示例
select语句是Go语言中用于处理通道操作的一种机制。它可以同时监听多个通道的读写操作,并在其中任意一个通道就绪时执行相应的操作。
通过使用select语句,我们可以实现对多个通道的并发操作,并根据就绪的通道执行相应的操作。这在处理并发任务时非常有用。
- Go语言如何通过goroutine和channel实现并发的 ?
Go语言通过goroutine和channel实现并发。goroutine是一种轻量级的线程,可以同时执行多个goroutine,而不需要显式地管理线程的生命周期
- Go语言中的runtime包是用来做什么的 ?
runtime包是Go语言的运行时系统,提供了与底层系统交互和控制的功能。它包含了与内存管理、垃圾回收、协程调度等相关的函数和变量。
- Go语言中的垃圾回收是如何工作的 ?
Go语言中的垃圾回收器(Garbage Collector)是自动管理内存的机制,用于回收不再使用的内存。垃圾回收器会自动检测不再使用的对象,并释放其占用的内存空间。
- G o的接口是什么 ?
在Go语言中,interface也就是接口,被用来指定一个对象。接口具有下面的要素:
- 一系列的方法;
- 具体应用中并用来表示某个数据类型;
- 在go中使用interface来实现多态。