某云大厂面试之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将一个分支的变更应用到另一个分支上,常用于保持历史记录整洁。

相关推荐
MarkHD4 小时前
GitHub Copilot实战教程:AI编程助手的完整使用指南
github·copilot·ai编程
大写-凌祁8 小时前
零基础入门深度学习:从理论到实战,GitHub+开源资源全指南(2025最新版)
人工智能·深度学习·开源·github
悟乙己9 小时前
Github | MoneyPrinterTurbo:自动化视频内容生成系统
自动化·github·音视频
程序员爱钓鱼10 小时前
Go语言实战案例 — 工具开发篇:实现一个图片批量压缩工具
后端·google·go
雁于飞10 小时前
vscode中使用git、githup的基操
笔记·git·vscode·学习·elasticsearch·gitee·github
在未来等你10 小时前
Kafka面试精讲 Day 13:故障检测与自动恢复
大数据·分布式·面试·kafka·消息队列
ChinaRainbowSea12 小时前
7. LangChain4j + 记忆缓存详细说明
java·数据库·redis·后端·缓存·langchain·ai编程
舒一笑12 小时前
同步框架与底层消费机制解决方案梳理
后端·程序员
minh_coo12 小时前
Spring框架事件驱动架构核心注解之@EventListener
java·后端·spring·架构·intellij-idea