后端面试接触golang

go调度器:GMP模型,线程运行是goroutine的实体,调度器的功能是把可运行的goroutine分配到工作线程上。

(1)我们通过go func()来创建一个goroutine

(2)有两个存储G的队列,局部调度器P的本地队列,一个是全局G队列。新建的G会保留在P的本地队列,如果P的本地队列满了就保留在全局中。

(3)G只能运行在M中,一个M必须有一个P,M与P是1:1的关系。

(4)一个M调度G的过程,必须是一个循环机制;

(5)当M执行一个G如果发送syscall和阻塞,M会阻塞,如果当前有一部分G,runtime把M从P中摘除,再新建服务这些P;

(6)当M系统调用结束时候,这个G会尝试获取一个空闲的P执行,并放入到这个P的本地队列。

TCP协议之握手和挥手:TCP是一种面向连接的,可靠的,基于字节流的传输层通信协议,是端到端的传输,TCP提供稳定的链接服务,连接三次握手进行初始化的,又因TCP是双工模式,所以需要四次挥手关闭连接。

第一次握手:建立连接时,由客户端发送Sync包到服务端,并进入SYN_SEN状态,等待服务端确认;

第二次握手:服务端收到Sync包,确认客户端的Sync包,再给客户发送一个Sync包,进入SYN_RECV状态,等待客户端接受确认;

第三次握手:客户端接到服务端的Syn+ack包,向服务端发送确认包ack,之后客户端和服务端都进入ESTABLISH状态,表示TCP连接成功,即完成三次握手。

四次挥手,终止TCP连接,就是指断开一个TCP连接时需要客户端和服务端一共4个包确认链接的断开,双端都发送Fin包,首先关闭一方主动关闭,另一方则被动关闭。

第一次挥手:客户端发出连接释放报文Fin包,并停止发送数据,客户端进入FIN-WAIT-1状态。

第二次挥手:服务端接收到释放报文,发出确认ACK包,服务端进入CLOSE-WAIT。

第三次挥手:服务端将最后的数据发送完毕,向客户端发送释放报文Fin包,服务端进入LAST-ACK状态。

第四次挥手:客户端接收到服务端的连接释放报文,必须发出确认,客户端进入TIME-WAIT状态。此时TCP链接还没有释放,需经过2*MSL(最长报文寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。

服务端收到客户端的确认即进入CLOSED状态。

切片:是数组连续片段的引用,结构体包含数组的指针,数组的量和容量。

切片的扩容就是append,如果在容量之内就append;超过了容量底层数组会复制到新的数组上去,容量扩充2倍,再append。

锁:保证线程安全,主要针对多个线程对一个全局变量修改,如果涉及读写用读写锁更好。

make和new的区别:new是golang的内建函数,用于分配内存,其中,第一个参数是类型,返回是类型的执政,其值被初始化为“零”;make是Golang的内建函数,仅用于分配和初始化slice、map以及channel类型的对象;返回具体类型,而不是指针。

Mysql索引底层原理:B+树存储的是数据的地址,一个节点可以存很多个数据,算法复杂度O(h*logn),大大减少了磁盘IO的读写次数。

go struct能不能比较:结构体里面有没有不可以比较的类型,切片类型不可以比较;譬如slice和map。

defer:defer调用链会在函数返回中增加一个函数调用,这个函数不是普通的函数,是在函数返回之后执行的。defer一般用来释放内存变量,遵循先进后出的原则。

select的作用:一个select语句用来选择哪个case中的发送或接收操作可以被立即执行。他的case涉及到channel有关I/O操作,当I/O操作发生时,除非相应的操作。如果有一个或者多个I/O操作,select会随机选择一个,否则会选择default;没有default,会阻塞。

context包的用途:context包提供上下文机制,在gourtine之间传递dealine,timeout,或者其他值请求信息。创建根 Context:context,backgroud;

channel无缓存和有缓存的区别:无缓存是来了个,消费一个;无缓存是未消费也可以继续入值,除非队列满了。

如何获取长连接:主要依赖Transport,Transport缓存了长连接,在大量请求http的场景;对连接的限制,譬如最大连接数,每个连接的超时时间。

map如何顺序读取:map不能顺序读取,因为他无序,想要有序就是把key放入切片,对切片排序。

实现set:Set主要是元素不能重复,和map的key一样。

var Exists = struct{}{}

//set类型
type Set struct {
  m map[interface{}]struct{}
}

//返回一个set
func New(items ...interface{}) *Set {
    s := &Set{}
    s.m = make(map[interface{}]struct{})
    _ = s.Add(items...)
    return s
}

func (s *Set) Size() int {
   return len(s.m)
}

// 添加元素
func (s *Set) Add(items ...interface{}) error {
   for _, item := range items {
      s.m[item] = Exists
   }
   return nil
}

//删除元素
func (s *Set) Remove(val int) {
  delete(s.m, val)
}

//获取长度
func (s *Set) Len() int {
   return len(s.m)
}

// 清空Set
func (s *Set) Clear() {
  s.m = map[interface{}]struct{}
}

// 遍历set
func (s *Set) Traverse() {
  for v := range s.m {
    fmt.Println(v)
  }
}

// 包含
func (s *Set) Contains(item interface{}) bool {
  _, ok := s.m[item]
  return ok
}
  • 实现消息队列(多生产者,多消费者):可以用channel,ch <- x ;用range和select遍历channel。
  • 大文件排序:利用堆实现优先队列,head底层是树pop算法复杂度是O(log(n))。
type InitHeap []int

func (h InitHeap) Len() int { return len(h) }
func (h InitHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h InitHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *InitHeap) Push(x interface {}) {
    *h = append(*h, x.(int))
}
func (h *InitHeap) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n - 1]
    *h = old[0: n - 1]
    return x
}
  • Golang内存分配:golang的内存分配源自Google的tcmalloc算法,核心思想是内存的多级管理,进而降低锁的粒度;将内存按需划成大小不一的块,减少内存的碎片化。为每个p,也就是go协程调度模型了里面的逻辑处理器维护一个mcache结构体的独立内存池,只有当该内存池不足时,才会向全局mcentral和mheap结构体管理的内存池申请。为每一个P维持一个私有的本地内存池,从而不用加锁,加快了内存分配速度。只有在本地P的内存池被消耗完,或者申请的内存太大时,才会访问全局的内存池,大大减少了多线程下对全局内存池访问带来的竞争系统消耗。

  • Golang垃圾回收:GC机制三色标记,遍历根对象的第一层标记为灰色,不可达标记为白色;将灰色对象的下一层可达对象标记为灰色,自身标记为黑色;多次重复步骤2,直到灰色对象为0,只剩下白色对象和黑色对象;sweep白色对象。

  • Golang实现单例模式:懒汉模式(加锁)、或者用Once:         

懒汉模式:

type Singleton struct {
	num int
}

var ins  *Singleton
var mu sync.Mutex

func GetInstance() *Singleton {
	if ins == nil{
		mu.Lock()
		defer mu.Unlock()
		ins = &Singleton{}
	}
	return ins
}

Once:

type Singleton struct {
	num int
}

var ins  *Singleton
var once sync.Once

func GetInstance() *Singleton {
	once.Do(func() {
		ins = &Singleton{}
	})
	return ins
}
  • 基本排序,哪些是稳定的:插入排序,稳定;选择排序,不稳定;堆排序,不稳定;冒泡排序,稳定;快速排序,不稳定;归并排序,稳定。
  • Get和Head:都是请求资源,get方法会获取实际的资源,而head方法只返回响应头,属于Get请求的轻量版,避免传输body的浪费。
  • 401/403: 401是未授权,403是服务器禁止。
  • http能不能一次链接屡次请求,不等后端返回:http本质上是使用socket连接,因此发送请求,接写入tcp缓冲,是可以多次进行的,这也是http是无状态的原因。
  • TCP和UDP的区别和优缺点:TCP是面向连接的,UDP是面向无连接的;TCP提供可靠的服务,也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按需到达;UDP尽最大努力交付,即不保证可靠交付,适用于高速传输和实时性要求较高的通信和广播领域。
  • time-wait:就是tcp释放连接的四次挥手后的主动关闭连接方的状态。time-wait的持续时间是2MSL,MSL是Maximum Segment Lifetime,译为报文最大生存时间;原因1:保证客服端发送的最后一个ack报文段送达服务器,断开不能按正常步骤进入close状态导致服务器资源的浪费。原因2:2MSL时间足以让报文段从网络消失,不然对面可能会收到异常的SYNC包。
  • 数据库创建索引:CREATE INDEX myIndex ON db(keyname);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值