关于 Golang 的几个面试题解析

2023-06-12 14:43:47 浏览数 (1)

嗨, 你们好, 我是 leoay, 今天我想写一篇文章分析一下 Golang 中的几个常见的面试题。

当然,因为这个号也只是刚开始写 Golang 相关的技术文章,所以刚开始也不打算写太多关于面试的技术文章。

这篇文章主要是用来制造气氛的, 毕竟面试求职,技术变现是这个号的主旋律, 说到技术变现, 我觉得对于技术人来说最简单直接的还是求职, 如果能进大厂, 涨薪妥妥的。

所以,后面我会重点关注这方面,关注技术面试。

不过今天只是简单写几个,另外 B 站毛大的《 Go 进阶训练营》第1期这周也要毕业了, 后面我准备写一系列的文章,分享一下我学习这套课程的笔记和收获,敬请期待!

好了,废话不多说,开始今天的正题。

1. go struct能不能比较

不能。因为是强类型语言,所以不同类型的结构不能作比较,但是同一类型的实例值是可以比较的,实例不可以比较,因为是指针类型。其实这个问题在C语言中也有。

2. 下面这行代码输出什么, 为什么?

代码语言:javascript复制
func b() {
    for i := 0; i < 4; i   {
        defer fmt.Print(i)
    }
}

输出:3 2 1 0, 因为 defer 后面的表达式遵循“先进后出,后进先出”

3. Go 网络编程中怎么实现长连接?

原理同短连接一样,但是 client 端要设置超时时间,然后循环读取服务端返回的 Response

4. 什么是 Channel,为什么它可以做到线程安全?

Channel 是Go中的一个核心类型,可以把它想象成一个可以用于传递数据的通道,不过是用在并发编程中的, Channel 也可以理解是一个先进先出的队列,通过管道进行通信。

Golang 的 Channel, 发送一个数据到 Channel 和从 Channel 接收一个数据都是原子性的。

Go 的设计思想就是, 不要通过共享内存来通信,而是通过通信来共享内存,前者就是传统的加锁,后者就是 Channel。

也就是说,设计 Channel 的主要目的就是在多任务间传递数据的,本身就是线程安全的。

5. 说一下进程、线程以及协程的区别

进程进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。

每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。

线程线程是进程的一个实体, 线程是内核态, 而且是CPU调度和分派的基本单元, 它是比进程更小的能独立运行的基本单位。

线程自己基本上不拥有系统资源, 只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈), 但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

线程间通信主要通过共享内存, 上下文切换很快, 资源开销较少, 但相比进程不够稳定容易丢失数据。

协程 协程是一种用户态的轻量级线程, 协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。

协程 调度切换时, 将寄存器上下文和栈保存到其他地方, 在切回来的时候, 恢复先前保存的寄存器上下文和栈, 直接操作栈则基本没有内核切换的开销,可以不加锁地访问全局变量, 所以上下文的切换非常快。

6. Go 中对 nil 的 Slice 和空 Slice 的处理是一致的吗

首先 Go 的 JSON 标准库对 nil slice 和 空 slice 的处理是不一致的。

通常错误的用法如下, 会报数组越界的错误, 因为只是声明了slice, 却没有给实例化的对象, 因为默认情况下 slice 长度为0。

代码语言:javascript复制
 var slice []int
 slice[1] = 0

此时 slice 的值是 nil,这种情况可以用于需要返回 slice 的函数,当函数出现异常的时候,保证函数依然会有 nil 的返回值。

empty slice 是指slice不为nil,但是slice没有值,slice 的底层的空间是空的,此时的定义如下:

代码语言:javascript复制
slice := make([]int,0)
slice := []int{}

当我们查询或者处理一个空的列表的时候, 这非常有用, 它会告诉我们返回的是一个列表, 但是列表内没有任何值。

总之, nil sliceempty slice 是不同的东西, 需要我们加以区分的。

这两者的区别就好像“我有一个空的桶”和“我有一个体积为0的桶”的区别。

7. Golang 中除了加 Mutex 锁以外还有哪些方式安全读写共享变量

Golang 中 Goroutine 可以通过 Channel 进行安全读写共享变量, 还可以通过原子性操作读写共享变量。

嗯,今天先写这么多吧,其实关于面试的题目有很多可以写, 后面有很多时间慢慢整理,今天先写到这里。

0 人点赞