1.new和make的区别?
2.golang内存管理?
3.调用一个函数传入结构体时,应该传值还是指针? 根据项目的实际情况来判断
传指针的话节约资源,那是相对于C来说的,对于go来说传指针,可能发生逃逸,原本分配在栈上的内存逃逸到堆上
4.线程有几种模型?
GMP模型,M对应的线程
5.在Liunx中线程有几种模型吗?
6.Goroutine的原理了解过吗?讲下实现和优势?
GMP模型
7.Goroutine什么时候发生阻塞,如果阻塞后调度器会怎么做?
数据库查询或者进行一个io操作,等待一个channel信号过来
8.在PMG中goroutine有那几种状态?
指的是状态流转,Grunning、Gayscall(c死可)、Gwaiting
类似于线程的三态图和五态图一样互相流转
9.在PMG中线程有那几种状态
它去抢占g,m去拿g的时候会有一个自旋和非自旋的状态
10.线程和协称分别占用的内存是多少?
在go的1.14版本上,2兆一个线程,协称是2kb
11.一个goroutine一直占用资源,PMG模型怎么解决?
goroutine是有调度资源,在GMP中goroutine是有正常模式和饥饿模式,如果有一个goroutine一直占用资源的话,
这个goroutine会转换为饥饿模式,然后会强行的将等待在最前面的goroutine去分配使用。
12.一个goroutine一直占用资源,PMG模型怎么通知它?
通过信号量协作,原来最开始是协作式,现在是信号协作。信号和信号量协作式不一样的。
12.如果若干个线程中一个线程出现OOM?
go的话如果一个线程出现OOM,他就会kill掉,其他线程不会出现影响。
13.如果goroutine出现OOM?
13.项目中如果出现bug,你们怎么去定位的?
我们现在除妖bug的话,主要线上有链路追踪,基本上看看链路就可以看出来
go用pprof可以抓到火焰图,跟一些其他的数据
14.项目中的错误处理是怎么做的?
就是err向上抛,if err != nil,当然会看这个err会不会影响下面的进程,如果说影响就往上抛,不影响直接
忽略掉,或者打一个日志记录下就可以了
15,。如果若干个goroutine,其中一个发生panic,会发生什么?
看下这个goroutine中有没有做painc捕获,如果没有做整个程序都会crush掉,如果做了真个程序都会不影响
16.defer可以捕获到goroutine底下的子goroutine抛出来的panic吗?
不行,子goroutine的话你必须在default里面的recovery,父线程或者父goroutine或者最上层,是不能捕获下层的
17.你们的错误处理要是写很多的if err != nil 会有很多重复的代码,有没有去有优化呢?
我们目前就是这样使用,也想不出其他的。除非要么就是做panic直接往最上层抛,不然好像也没有什么多的好办法
如果你想处理这个函数他是否返回error,那你必须要截获他返回的error里到底是不是等于nil,反正目前我们就是这
样做的if error ,当然社区里面常说的就是一行代码三行 if error != nil,我们也没有相处更好的办法
18.你们会自己定义一些error吗?
因为我们现在就是用grpc做RPC框架,然后我们对自己定义了error对象,这样就方便我们gRPC的服务互相调用,可以通过grpc的
error,grpc的error去透传error信息,这样调用方也能直接拿到被调用方的error的code码跟message和一些deatile详细信息
19.grpc用的原生的grpc吗?
我们现在用的是原生的gpc,然后我们自己封装了下利用grpc gateway就提供了HTTP方式,就是每个HTTP,grpc都提供了
20.grpc gateway怎么做的?
grpc的社区有一个get gateway的库,他是可以直接通过proto的文件,里面的描述信息可以生成HTTP的访问方式
21.你们的proto文件是怎么管理的
22.使用gin框架吗?
23.gin怎么做参数校验?
定义一个结构体然后用它的tag里面去写你需要验证你写类型还有一些限制,然后用他的shouldBind还是shouldBindJson来做参数校验,
然后返回是否有error
24.go里面解析tag用的是?
用的是反射来实现的,反射可以获取他的原数据,然后可以获取到它的tag及描述什么的
25.反射的原理是什么?
反射就是用go里面的Reflect的包,然后获取对象的type跟value的一些原数据,然后通过type和value去获取更加详细的数据
还有它的一些方法,当然你也可以通过这些方法进行调用什么的。
26.你们项目中实际使用过Reflect(瑞福莱特)吗?
有用到,我们自己的grpc业务框架就统一定义了参数的校验,参数校验就是通过反射,就是tag里面放一些它是否是手机号类型,
或者是email类型的这些具体的规则,然后通过具体验证的方法,在参数验证方法里面中传进来参数验证的定义的struct,通过反射中tag获取
它的定义,然后去判断是否符合条件。
27.反射实际应用
package main
import (
"fmt"
"reflect"
)
type Animal struct {
}
func (m *Animal) Eat() {
fmt.Println("Eat")
}
//实现使用过,字符串函数名 调用函数
func main() {
animal := Animal{}
value := reflect.ValueOf(&animal)
f := value.MethodByName("Eat")
f.Call([]reflect.Value{})
}
28.golang的锁机制了解过吗?
读写锁用过,Mutex互斥锁
29.锁的模式
正常模式和饥饿模式是Mutex(马特克斯),它并不是PMG模型
30.在项目中用到锁了吗?
项目中读写锁用到比较多点,比如说全局的一个变量,就拿map来说,map是协程不安全的,如果多个协程对他进行
修改的话,那么他会报错,所以我们在使用map的地方,会加上一个读写锁,有时候直接用写锁,然后在修改他之前
Lock处理完后把他释放做到一个占用,防止并发去修改它这种。
现在更多的使用sync.Map就是协程安全的Map,那么更简单
30.在项目中用到channel了吗?
在项目中用到的少,大部分用waitGroup,坐下并发的请求
30.channel需要注意的地方吗?
不能在close之后再向channel发送信息
30.在数据库中用到锁了吗?
全局锁、行锁、表锁
31.redis实现分布式锁?
用redis实现redlock