Go面试精萃(应付go语言层面仅需一篇文章:持续更新)

目录

[TOC]

channel

  1. 对未定义的channel(也就是nil)进行读写都会被阻塞
  2. 对已关闭的channel
    进行读,会得到类型的零值(int就是0,string就是空字符串)
    进行写,会发生panic
    进行重复关闭,会发生panic
  3. channel底层实现原理(通过通信来共享内存)
    基础:
         发送方和接收方都是goroutine,通常与select结合来管理多个goroutine之间的通信
         ch := make(chan int)    //创建,得到一个hchan结构的指针
         data <- ch    //读
         ch <- 1        //写
         close(ch)    //关闭
    底层:
    由环形链表和双向链表以及锁实现
    • 环形链表做buf,用来写入的数据,作为缓冲,有两个指针用来指向写入位置(sendx)和读取位置(recvx)。
    • 双向链表是recvq和sendq,分别存放待写入的G(goroutine)和待读取的G,当缓冲buf写满了,那么要往channel写数据的G会在sendq中排队,阻塞着,把M让出来给其他G,直到有G来读取数据时被唤醒。同理recvq也是一样,当没有数据读了,那么读数据的G也在recvq中阻塞着。
    • 锁Lock,保证G能按顺序进入recvq和sendq队列,先进先出。
    • 优化特性:当读数据的G1被阻塞时,此时有写数据G2来写数据,此时不是将channel锁住,数据先写入buf,而是直接从G2复制数据到G1,从而减少了内存copy。

map

  1. 对nil的map读值,得到零值
  2. 对nil的map添加值,会发生panic
  3. 对nil的map删除值,不会报错
  4. map底层实现原理
    基础:
     go的map是非线程安全的,也就是多个协程取写map可能会异常中断报错,不是并发安全。sync.map是线程安全的。
    底层:
    采用hmap结构,count记录元素个数,记录B(数量)个buckets是一个bmap结构的数组,数据存储在bmap中,每个存储8个kv,一旦满了就会溢出指针overflow指向下一个bmap。
    读取:读取时计算key的hash,通过最后B位找到对应的bmap,通过前8位找到bmap中对应的值。
    扩容:oldbuckets指针用于指向扩容前的buckets数组
    • map读取是无序的,原因是map写入是无序的,且还有扩容机制(倍数扩容,等量扩容)

slice

切片的底层是数组,数组是值传递(深拷贝),slice(切片)是引用传递(浅拷贝)
nil切片指向地址为0
底层:
ptr指向数组的指针,len为长度,cap为容量
扩容机制:
当容量小于1024,扩容后为原来的2倍
当容量不小于1024,扩容后为原来的1.25
本作品采用《CC 协议》,转载必须注明作者和本文链接
GitHub地址:github.com/bllon
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!