某云大厂面试之Go 实际问题及答案

  1. Go的调度

    • Go使用goroutine进行并发处理,调度器通过M:N模型将goroutine调度到操作系统线程上。Go的调度是由Go运行时的调度器(scheduler)管理的,使用GOMAXPROCS来控制并发的最大CPU核数。调度器使用抢占式调度,并在goroutine之间动态分配计算资源。​编辑
  2. Go struct能否比较

    • Go中的struct是可以比较的,但有一些限制。结构体中的字段必须是可以比较的类型。如果结构体包含不可比较的字段(如切片、映射、函数等),则该结构体就不可比较。​编辑
  3. Go defer(for defer)

    • defer语句用于在函数返回前执行清理操作。对于for defer,如果defer放在for循环内,defer会延迟执行,但它会根据循环的每次迭代被调用,因此每次循环结束时都会注册一个defer,直到for循环结束。

​编辑4. select可以用于什么

  • select语句主要用于多个channel之间的选择,它会等待多个channel中的一个准备好(发送或者接收),然后执行相应的代码块。常用于多goroutine间的同步和消息传递。
  1. context包的用途

    • context包用于在不同的goroutine之间传递请求作用域的数据,特别是在处理并发任务时,提供了取消信号、超时控制等功能。常用于HTTP请求、数据库操作等长时间运行的任务。
  2. client如何实现长连接

    • Go的http包中的http.Client支持持久连接(HTTP Keep-Alive)。通过复用同一个http.Client实例,可以实现长连接。连接会被复用,直到超时或手动关闭。
  3. 主协程如何等待其余协程完再操作

    • 使用sync.WaitGroup可以等待多个goroutine完成。主协程调用WaitGroup.Add(n)来设置等待的goroutine数,其他goroutine调用WaitGroup.Done()来减少等待数,最后主协程调用WaitGroup.Wait()等待所有goroutine完成。
  4. slice,len,cap,共享,扩容

    • len返回切片的元素个数,cap返回切片的容量(最大存储空间)。切片共享底层数组,因此修改切片元素会影响到其他共享该数组的切片。切片扩容时会创建一个新的底层数组,原有数组会被拷贝到新数组中。
  5. map如何顺序读取

    • Go中的map是无序的,不能保证元素的顺序。如果需要有序读取,可以先将map的键提取到一个切片中,然后对该切片进行排序,最后根据排序的键顺序访问map中的元素。
  6. 实现set

    • Go本身没有提供set类型,但可以通过map实现一个set。例如:

    ```go

    type Set struct {

    data map[int]struct{}

    }

func NewSet() *Set {

return &Set{data: make(map[int]struct{})}

}

func (s *Set) Add(value int) {

s.data[value] = struct{}{}

}

func (s *Set) Contains(value int) bool {

_, exists := s.data[value]

return exists

}

```

  1. 实现消息队列(多生产者,多消费者)
    • 可以使用Go的channel来实现消息队列。例如,使用goroutine来模拟多个生产者和消费者:
      ```go
      package main

import (

"fmt"

"sync"

)

func main() {

var wg sync.WaitGroup

ch := make(chan int, 10)

// 生产者

go func() {

defer wg.Done()

for i := 0; i < 5; i++ {

ch <- i

fmt.Println("Produced:", i)

}

}()

// 消费者

go func() {

defer wg.Done()

for i := 0; i < 5; i++ {

msg := <-ch

fmt.Println("Consumed:", msg)

}

}()

wg.Add(2)

wg.Wait()

}

```

  1. 大文件排序

    • 对于大文件排序,通常需要外部排序。将文件分块,分块排序后合并。可以通过iobufio进行高效的文件读写。
  2. 基本排序,哪些是稳定的

    • Go内置的sort包提供的排序算法是基于快速排序和插入排序的,通常是不稳定的。稳定排序的例子有归并排序。
  3. HTTP GET和HEAD

    • GET请求用于获取资源,服务器返回资源的内容。HEAD请求与GET类似,但不返回响应体,只返回响应头,常用于检查资源的状态。
  4. HTTP 401, 403

    • 401:表示未授权,通常在请求头中缺少有效的身份验证信息时返回。

    • 403:表示禁止访问,服务器理解请求但拒绝执行,常因权限不足而返回。

  5. HTTP Keep-Alive

    • HTTP Keep-Alive是一种在同一TCP连接中复用多个HTTP请求和响应的机制。减少了TCP连接的建立和关闭开销,提高了性能。
  6. HTTP能不能一次连接多次请求,不等后端返回

    • 可以。HTTP/2协议支持在同一个连接上并发多个请求和响应,且不需要等待前一个请求返回即可发送后续请求。
  7. TCP与UDP区别,UDP优点,适用场景

    • TCP是面向连接的协议,保证数据的可靠性、顺序性和完整性;而UDP是无连接的协议,不保证数据可靠性。UDP的优点是速度快、开销小,适用于实时性要求高、容错能力强的场景(如视频流、语音通信等)。
  8. TIME-WAIT的作用

    • TIME-WAIT状态是TCP连接的四次挥手中的最后一步,目的是确保数据完全传输并防止旧数据包影响新连接。
  9. 数据库如何建索引

    • 建立索引可以通过SQL语句CREATE INDEX来实现。通过在表的字段上创建索引,可以加速查询操作,但会增加插入和更新操作的开销。
  10. 孤儿进程,僵尸进程

    • 孤儿进程是其父进程已退出,但仍然运行的进程。僵尸进程是已经终止,但其父进程未收集其退出状态的进程。可以通过wait()函数来清理僵尸进程。
  11. 死锁条件,如何避免

    • 死锁发生时多个进程相互等待对方释放资源。避免死锁的方法包括资源排序、加锁时避免嵌套锁和使用timeout机制等。
  12. Linux命令,查看端口占用,CPU负载,内存占用,如何发送信号给一个进程

    • 查看端口占用:netstat -tulnlsof -i:端口号

    • 查看CPU负载:topuptime

    • 查看内存占用:free -mtop

    • 发送信号:kill -SIGTERM <PID>kill -9 <PID>

  13. Git文件版本,使用顺序,merge跟rebase

    • 文件版本:Git通过git addgit commit来管理文件的版本。

    • 使用顺序:git pull获取远程更新,git add跟踪更改,git commit提交更改,git push推送到远程仓库。

    • Merge:merge将两个分支的历史保留,并将它们合并。Rebase:rebase将一个分支的变更应用到另一个分支上,常用于保持历史记录整洁。

相关推荐
阿蒙Amon17 分钟前
C#每日面试题-常量和只读变量的区别
java·面试·c#
Victor35625 分钟前
Hibernate(42)在Hibernate中如何实现分页?
后端
Victor35631 分钟前
Hibernate(41)Hibernate的延迟加载和急加载的区别是什么?
后端
猪猪拆迁队44 分钟前
2025年终总结-都在喊前端已死,这一年我的焦虑、挣扎与重组:AI 时代如何摆正自己的位置
前端·后端·ai编程
程序员小白条1 小时前
面试 Java 基础八股文十问十答第八期
java·开发语言·数据库·spring·面试·职场和发展·毕设
ConardLi1 小时前
SFT、RAG 调优效率翻倍!垂直领域大模型评估实战指南
前端·javascript·后端
Hooray2 小时前
2026年,站在职业生涯十字路口的我该何去何从?
前端·后端
唐叔在学习2 小时前
还在申请云服务器来传输数据嘛?试试P2P直连吧
后端·python
开心猴爷2 小时前
iOS 代码混淆在项目中的方式, IPA 级保护实践记录
后端
xlp666hub2 小时前
Linux 设备模型学习笔记(1)
面试·嵌入式