1、进程和线程的区别
答:计算机由CPU和操作系统组成,CPU执行计算任务,操作系统执行资源调度任务。在操作系统上会有很多软件可以执行,每个软件的执行系统都会单独分配资源,即一个独立的进程,进程和进程之间是相互独立的,每个进程有单独的分配内存空间,进程是系统进行资源分配和调度的一个独立单位。每个进程都至少有一个线程,线程执行代码程序,共享进程的数据资源,线程是轻量级的,有自己的堆栈、寄存器,共享进程空间,一个进程可以有多个线程,并发执行由CPU控制时间段,做上下文切换,上下文切换由调度器控制,在不同的时间段内执行不同的线程,每次上下文切换的时候都保存当前状态,下次回来时重新从中断点开始接着执行。线程切换是轻量级的,相对于进程切换消耗更少的资源。进程由内存空间(代码、数据、进程空间,打开的文件)和一个或者多个线程组成。一个标准的线程由线程ID,当前指令指针PC,寄存器和栈组成。线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位,线程是一个进程中代码的不同执行路线。
2、go的调度
答:go支持多线程,在代码中我们可以通过关键字go创建一个线程,多线程并发执行,由系统调度切换上下文,即在不同的时间段分间断的执行不同的线程内容;
3、go struct能不能比较
Go是强类型语言,不能隐性转换,不同类型不能比较。但同一类型的实例值可以比较的。实例不可以比较,因为是指在类型
4、go defer
先进后出,后进先出
5、select可以用于什么,常用语gorotine的完美退出
select是Go的一个控制结构,类似于用于通信的switch语句,每个case语句必须是一个通信操作,要么是发送要么是接收。select随机执行一个可运行的case.如果没有case可以运行,它将阻塞,直到有case可运行。一个默认的子句总是可运行的。select会循环检查条件,如果有满足则执行并退出,否则一直循环检测,阻塞运行,直到有case可以运行。
6、context包的用途Context通常被译作为上下文,它是一个比较抽象的概念,其本质是【上下上下】存在上下层的传递,上会把内容传递给下。在Go语言中,程序单元也就指的Goroutine
答:系统在做线程调度的时候,会将产生中断,保存当前线程状态,切出到其他线程,执行其他线程,之后返回这个中断的线程,取出数据继续执行该线程。多线程并发就是CPU的时间片段之行,CPU总是顺序执行任务的,要达到并发就要不断的在不同线程间快速切换,切换过程中就会有线程的中断,数据的保存,线程的重启,数据的重读,上下文就是线程的调度,中断线程,保存数据,重读数据,继续执行线程。
7、主协程如何等待其余协程操作完再执行
利用channl和select,select是Go的控制语句,类似于switch,每个case语句都是一个通信操作,发送或者接收。如果没有满足条件的case,select会一直循环监听,阻塞线程,直到有case语句被执行
8、slice,len,cap,共享,扩容
slice的数据结构由指向数组的指针、len,cap组成,在使用append扩容的时候,会查看有没有可用的连续内存,如果有直接添加,没有就重新组成一个大的数组,扩容总是cap的倍数执行,如果原切片的容量大于等于1024时,每次增加25%。扩容slice后,指向的数组的指针发生改变,已不再指向原数组
9、map如何顺序读取
map是无序的,不能顺序读取,如果想要顺序读取,先要将key顺序化。用切片将排序,再给map依次赋值
10、实现SET功能
// 实现set
type Set struct {
sync.RWMutex
v map[string]bool
}
func New() *Set {
return &Set{
sync.RWMutex{},
map[string]bool{},
}
}
// 不重复 添加
func (s *Set)AddItem(val string) {
s.Lock()
defer s.Unlock()
s.v[val] = true
}
// 删除
func (s *Set)RemoveItem(val string) {
s.Lock()
defer s.Unlock()
delete(s.v, val)
}
11、实现消息队列(多生产者,多消费者)
带缓存channel 队列结构,先进先出
12、大文件排序
归并排序,分而治之,拆分为小文件,在排序
13、基本排序,哪些是稳定的
快速排序,冒泡排序,插入排序
14 http中get和head的区别
head请求中信息放在请求投中,没有返回体,get可在请求链接中拼接参数,有请求信息返回。
用head请求可以判断某个资源是否存在
15 401,403,404,502,504错误
400:请求格式错误
401:用户无权限
403:拒绝访问
404:找不到服务
502:网关错误
504:服务器错误
16、http重连接机制 keep-alive
请求头中加入Connection: keep-alive来告诉对方这个请求响应完成后不要关闭,下一次咱们还用这个请求继续交流。
17、http能不能一次连接多次请求,不等后端返回
http本质上市使用socket连接,因此发送请求,接写入tcp缓冲,是可以多次进行的,这也是http是无状态的原因
18、主键索引和唯一索引的区别
主键是一种约束,唯一索引是索引,本质不同。主键创建时默认创建唯一索引。主键不能为空,主键可以当作外键,主键唯一。唯一索引可以创建多个
26、项目里的微信支付这块,在支付完微信通知这里,收到两次微信相同的支付通知,怎么防止重复消费
redis锁(setNX)
28、Go的反射包怎么找到对应的方法
29、Redis基本数据结构
31、Mysql的索引有几种,时间复杂度
4种,主键、唯一、普通、全文,B+树,时间复杂度O(logn)
32、InnoDb是表锁还是行锁,为什么
InnoDb即支持行锁,也支持表锁,只有在通过索引检索数据时使用行锁。
33、Go的channel(有缓冲和无缓冲)
34、退出程序时怎么防止无缓存的channel没有消费完
退出程序时将生产者关闭,不会有多余的数据给消费者消费
35、用过什么消息中间件之类吗?
38、生产者消费者模式,利用channel
var wg sync.WaitGroup
// 生产者
func Send(ch chan int){
x := 0
defer func(){
close(ch)
wg.Done()
}()
for i:=0;i<10;i++{
x++
ch <-
}
}
// 消费者
func Receive(ch chan int){
defer func(){
close(ch)
wg.Done()
}()
for x := range ch {
fmt.Println(x)
}
}
func main(){
ch := make(chan int)
wg.Add(2)
go Send(ch)
go Receive(ch)
wg.Wait()
fmt.Println("任务完成")
}
39、手写循环队列
// 循环队列
type CircleQueue struct{
queue []interface{}
tail int
front int
cap int
}
// 创建循环对例
func NewCircleQueue(n int) *CircleQueue {
loop := &CircleQueue{
make([]interface{},0,n),
0,
0,
n,
}
return loop
}
// 添加元素
func (c *CircleQueue)AddQueue(a interface{}) bool {
// 判断是否已经满了
if c.front == (c.tail+1)%c.cap {
return false
}
c.queue = append(c.queue,a)
c.tail = (c.tail+1)%c.cap
return true
}
// 删除元素
func (c *CircleQueue)DeleteQueue() bool {
if c.tail == c.front {
return false
}
c.queue = c.queue[c.front:]
c.front = (c.front+1)%c.cap
return true
}
// 获取长度
func (c *CircleQueue)Len()int {
// 当c.tail == c.front时循环队列,不一定为空
if c.tail == c.front && c.front != (c.tail+1)%c.cap{
return 0
}
return c.tail - c.front
}
40、如何保证循环队列线程安全
1.可以加锁。2.channel本身是一个带锁的队列,可以将结构体中的切片换成带缓存的channel
42、Linux会不会,只会几个命令,一共也就一百多个命令
43、TimeWait和CloseWait原因
45、看过什么源码,nsq(Go的消息中间件)
46、sync.Pool用过吗,为什么使用,对象池,避免频繁分配对象(GC有关),那里面的对象是固定的吗
49、证明二叉树的叶子节点跟度数为2的节点的关系
50、唯一索引和主键索引
52、字符串解析为数字(考虑浮点型)
53、单点登录,tcp粘包
54、手写洗牌
56、goroutine调度用了什么系统调用
57、进程虚拟空间分布,全局变量放哪里
58、有没有网络编程,有,怎么看连接状态?netstat,有哪些?ESTABLISHED,LISTEN等等,有异常情况吗?TIME_WAIT很多,为什么?
59、几种基本排序算法说一下,问了堆的时间复杂度,稳定性,为什么不稳定
快速排序、冒泡排序、插入排序
61、什么是主键
62、联合索引和唯一索引
63、越多的索引越好吗?
不是,占用资源,插入性能差
64、建立索引要注意什么
65、死锁?
66、tcp三次握手
67、http,https
68、状态码401,301,302,201
69、项目我说只有一台机子,所以用的单机部署,面试官说单机也可以部署多个,有什么方法吗?我说docker,问docker有哪些网络,不熟,dockerfile关键字,只答几个。顺便扯了下nginx转发。
70、数据库隔离级别,提交读会造成什么
71、go调度
72、goroutine泄漏有没有处理,设置timeout,select加定时器
73、mysql高可用的方案
读写分离
75、排序算法以及时间复杂度
77、go的线程,给他讲了跟goroutine调度
78、io模型,同步阻塞,同步非阻塞,异步
79、cookie和session
80、接口kps测试
81、redis分布式,如何减少同步延迟
93、go优缺点
94、go的值传递和引用
天生指针类型:map、channel、slice
值类型:数组
Golang默认采用值传递,即拷贝传递
区别:
函数调用数组时,默认会是值传递,在函数内部修改数组值,外部数组内容不会改变
如果传入的是map,内部修改完后,外部也会改变
有疑问加站长微信联系(非本文作者)