golang面试题

基础题

Go 的优势是什么?

  • 天然支持并发,通过Goroutine和通道实现的
  • 支持静态链接,也就是把依赖也打到可执行文件
  • 编译语言,效率更高,相对于php、、python、js

Go 程序中的包是什么?

相当于php中的命名空间 + 类库

make和new有什么区别?

数组和切片的区别是什么?

1、数组长度固定,切片长度不固定

2、数组是值类型,切片是引用类型。当切片传递给函数时,即使它是按值传递的,实际还是引用传递

channel有什么作用?

负责协程间通信

什么是 Goroutine?你如何停止它?

协程。使用context包停止

如何在运行时检查变量类型?

反射

defer关键字有什么作用?

提前定义好当前函数返回之前需要执行的代码,比如关闭文件或释放资源等操作

什么是交叉编译?

 在一个平台上生成可以在另外一个平台执行的文件。具体命令如下:

# 要去linux下执行
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
# 要去Mac下执行
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
# 要去win下执行
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go

进阶题

如何在Go语言中实现错误处理?

通过error 接口,处理非致命性错误,例如打开一个不存在的文件、例如网络请求失败需要重试

通过panic,处理致命错误,需要立即中断,例如数据库挂了

推荐方式:尽量使用error

并发同步是什么?在Go语言中,如何实现并发同步?

多个线程或协程并发执行。golang使用goroutine+channel来实现,需要考虑以下问题:

1、开启协程使用goroutine

2、协程间通信使用channel

3、数据竞争处理使用互斥锁(Mutex)、读写锁(RWMutex)、原子操作(Atomic)

例外:尽量避免使用全局变量

Go语言中的并发安全性是什么?如何确保并发安全性?

数据竞争问题。见上题3

Map是线程安全的吗?

线程不安全, 一个 goroutine 在对 map 进行写的时候,另外的 goroutine 不能进行读和写操作

Go语言的泛型是什么,它们有什么用途?

编写模板适应所有类型,简化代码,否则就需要用接口和类型断言。从1.18版本之后才支持

什么是反射,什么场景使用?

反射是指在程序运行时检查变量和值的类型,并且可以改变它们的值或者调用它们的方法。

使用场景:

1、结构体转json时换key的别名

2、判断变量类型执行不同的方法,如1.18版本之前实现泛型
 

如何进行垃圾回收的?

三色标记原理、写屏障

GMP调度流程

原子操作和锁的区别

在Go语言中,如何进行网络编程?

使用net包

互斥锁(Mutex)

使用场景:写操作频繁

什么是Mutex互斥锁?它在并发编程中的作用是什么?

Mutex互斥锁是一种并发控制机制,用于保护共享资源的访问,以防止多个goroutine同时对该资源进行修改。它提供了两个基本操作:Lock和Unlock。当一个goroutine获得了Mutex的锁时,其他goroutine将被阻塞,直到该goroutine释放了锁。

读写锁(RWMutex)

使用场景:读操作频频率远高于写操作

互斥锁是完全互斥的,实际上我们更多的场景是读多写少的,当我们并发的读取不涉及修改的资源是没必要加锁的,这时我们使用读写锁sync.RWMutex是一种更好的选择。

当一个goroutine获取读锁之后,其他的goroutine如果获取读锁会继续获得锁,若果获取写锁就会等待;

当一个goroutine获取写锁之后,其他的goroutine无论获取读锁还是写锁均会等待。

有了Mutex为什么还需要RWMutex,解决了什么问题?

虽然Go语言中的Mutex互斥锁可以保证对共享资源的独占访问,但在大量并发读操作和少量并发写操作的场景下,Mutex会造成不必要的锁等待,影响性能。因此,引入了RWMutex读写锁,它在读锁占用的情况下,会阻止写操作,但不阻止读操作;在写锁占用的情况下,会阻止其他goroutine(读和写)进来,整个锁相当于由该goroutine独占。这样可以提高读操作的并发性,从而提高性能。因此,当需要明确区分reader和writer的协程场景,且是大量的并发读、少量的并发写时,可以考虑使用RWMutex替换Mutex

什么是 sync.Once

只执行一次,类似单例模式

sync.Pool 有什么用

需要重复分配、回收内存的地方可以用,如数据库连接池,从而减少并复用内存

有哪些常用的包,分别用来做什么?

WaitGroup:用于等待一组goroutine执行完毕,可以确保主goroutine不会过早退出

package main

import (
	"fmt"
	"sync"
	"time"
)

func worker(id int, wg *sync.WaitGroup) {
	defer wg.Done()
	time.Sleep(time.Second)
}

func main() {
	var wg sync.WaitGroup

	for i := 1; i <= 3; i++ {
		wg.Add(1)
		go worker(i, &wg)
	}
	wg.Wait()
	fmt.Println("All workers finished")
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值