Go教程

go面试

本文主要是介绍go面试,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

1、Make 和 new 区别

make和new都是内存的分配(堆上),但是make只用于slice、map以及channel的初始化(非零值);而new用于类型的内存分配,并且内存置为零。make返回的是引用类型本身;而new返回的是指向类型的指针。

 

2、切片和数组关系  引用类型和值类型  共享 扩容

 

数组是值类型,复制和传参复制整个数组。因此改变副本得值不会改变自身的值
数组支持 “==“、”!=” 操作符,因为内存总是被初始化过的。
切片是一个引用类型,它的内部结构包含地址(底层数组的指针)、长度和容量。切片一般用于快速地操作一块数据集合
当底层数组不能容纳新增的元素时,切片就会自动按照一定的策略进行“扩容”,此时该切片指向的底层数组就会更换。
“扩容”操作往往发生在append()函数调用时,所以我们通常都需要用原变量接收append函数的返回值。

 

3、go struct能不能比较

golang中数据类型

可比较:IntegerFloating-pointStringBooleanComplex(复数型)PointerChannelInterfaceArray

不可比较:SliceMapFunction

 

同一个struct的两个实例可比较也不可比较,当结构不包含不可直接比较成员变量时可直接比较,否则不可直接比较

可以比较,也不可以比较,可通过强制转换来比较,如果成员变量中含有不可比较成员变量,即使可以强制转换,也不可以比较

 

4、Go defer for defer

defer在匿名返回值和命名返回值函数中的不同表现

在for循环中使用defer可能导致的性能问题

调用os.Exit时defer不会被执行

 

5、Client 如何实现长链接

for 循环不断读取 server端返回的response

 

6、主协程如何等其余协程完再操作

channel通信(主协程阻塞等待数据,每当一个子协程执行完后,就会往 ch 里面写一个数据,主协程收到后会使 count–,当 count 减为 0,关闭 ch,主协程将不阻塞在 range ch)、sync.WaitGroup

 

7、Content 包用途

Context通常被译作上下文,它是一个比较抽象的概念,其本质,是【上下上下】存在上下层的传递,上会把内容传递给下。在Go语言中,程序单元也就指的是Goroutine

8、Channel 注意事项

已关闭的通道:

 

对一个关闭的通道再发送值就会导致panic。

对一个关闭的通道进行接收会一直获取值直到通道为空。

对一个关闭的并且没有值的通道执行接收操作会得到对应类型的零值。

关闭一个已经关闭的通道会导致panic。

使用_,ok 判断 channel 是否关闭

更多 https://www.dazhuanlan.com/kaierlong/topics/1556135

 

 

7、Select 可以用于什么

 

无阻塞获取值

select-default

func (w *wantConn) waiting() bool {
    select {
    case <-w.ready:
        return false
    default:
        return true
    }
}

 

超时控制

select-timer    例如等待tcp节点发送连接包,超时后则关闭连接

 
func (n *node) waitForConnectPkt() {
    select {
    case <-n.connected:
        log.Println("接收到连接包")
    case <-time.After(time.Second * 5):
        log.Println("接收连接包超时")
        n.conn.Close()
    }
}

 

类事件驱动循环

for-select模式,例如监控tcp节点心跳是否正常

func (n *node) heartbeatDetect() {
    for {
        select {
        case <-n.heartbeat:
            // 收到心跳信号则退出select等待下一次心跳
            break
        case <-time.After(time.Second*3):
            // 心跳超时,关闭连接
            n.conn.Close()
            return
        }
    }
}

 

 

 

8、Map 线程安全问题

9、进程、线程、携程关系

 

进程

 

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。

 

线程

 

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。

 

协程

 

协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

 

 

10、协程调度及调度时机

GMP 

 

调度时机

会阻塞的系统调用,比如文件io,网络io;
time系列定时操作;
go func的时候, func执行完的时候;
管道读写阻塞的情况;
垃圾回收之后。
主动调用runtime.Gosched()

https://studygolang.com/articles/34362?fr=sidebar

 

 

11、GC垃圾回收

12、Redis 数据持久化怎么做

13、逃逸分析

14、map如何顺序读取

map不能顺序读取,是因为他是无序的,想要有序读取,首先的解决的问题就是,把key变为有序,所以可以把key放入切片,对切片进行排序,遍历切片,通过key取值

15、异常和错误处理

16、微服务  服务注册发现怎么做的  链路追踪什么的  etcd相关

17、容器技术Docker相关  

18、K8s相关

19、http 40X 状态码  分别什么问题

20、Linux 常用命令 如端口占用 cpu负载 内存占用

端口占用:netstat -anp |grep 端口号

cpu负载:

top 命令第三行

 

%us:表示用户空间程序的cpu使用率(没有通过nice调度)

 

%sy:表示系统空间的cpu使用率,主要是内核程序。

 

%ni:表示用户空间且通过nice调度过的程序的cpu使用率。

 

%id:空闲cpu

 

%wa:cpu运行时在等待io的时间

 

%hi:cpu处理硬中断的数量

 

%si:cpu处理软中断的数量

 

%st:被虚拟机偷走的cpu

vmstat

 

内存占用

 

top 命令第四行

 

第四行:内存状态

 

总量:1020000k

 

已使用:144964k

 

空闲量:875036k

 

缓存的内存量:12456k

 

 

进程情况  PS

 

 

21、实现set

22、实现消息队列(多生产者,多消费者)

23、大文件排序

24、基本排序,哪些是稳定的

25、http get跟head

26、http keep-alive

27、http能不能一次连接多次请求,不等后端返回

28、tcp与udp区别,udp优点,适用场景

29、time-wait的作用

a、为了保证客户端发送的最后一个ack报文段能够到达服务器,因为这最后一个ack确认包可能会丢失,然后服务器就会超时重传第三次挥手的fin信息报,然后客户端再重传一次第四次挥手的ack报文。如果没有这2msl,客户端发送完最后一个ack数据报后直接关闭连接,那么就接收不到服务器超时重传的fin信息报(此处应该是客户端收到一个非法的报文段,而返回一个RST的数据报,表明拒绝此次通信,然后双方就产生异常,而不是收不到。),那么服务器就不能按正常步骤进入close状态。那么就会耗费服务器的资源。当网络中存在大量的timewait状态,那么服务器的压力可想而知。

b、在第四次挥手后,经过2msl的时间足以让本次连接产生的所有报文段都从网络中消失,防止下次连接出问题

30、孤儿进程,僵尸进程

31、数据库如何建索引

32、mysql索引为什么要用B+树

33、raft算法是那种一致性算法

共识算法  分布式一致性算法

34、raft有什么特点

 

与Paxos相比,Raft强调的是易理解、易实现,Raft和Paxos一样只要保证超过半数的节点正常就能够提供服务。

 

 

 

众所周知,当问题较为复杂时,可以把问题分解为几个小问题来处理,Raft也使用了分而治之的思想,把算法分为三个子问题:

 

 

 

  • 选举(Leader election)
  • 日志复制(Log replication)
  • 安全性(Safety)

 

分解后,整个raft算法变得易理解、易论证、易实现

 

35、怎么做服务发现的服务发现有哪些机制

36、锁 :死锁条件  如何避免

这篇关于go面试的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!