如何通过 Go 面试:常见问题汇总
Go(Golang)是构建高负载服务器应用和微服务最受欢迎的编程语言之一。Go 开发岗位的面试通常不仅考察语法知识,还要求理解内部机制:goroutine、通道、接口和内存管理。本文将逐一解析面试中最常问的 10 个问题,并附带代码示例和解释。
1. 数组和切片有什么区别?
这是一个理解 Go 基础的经典问题。
- 数组 — 是一个固定长度的相同类型元素序列。数组的大小是其类型的一部分。
- 切片 — 是一个动态结构,引用底层数组。切片可以增长并改变其大小。
// 数组 — 固定大小var arr [3]int = [3]int{1, 2, 3}// 切片 — 动态var slc []int = []int{1, 2, 3}
// 重要:arr 和 [4]int 是不同的类型// 切片通过引用传递(指向底层数组的指针)提示:如果需要改变长度——使用切片。如果需要保证固定大小——使用数组。
2. 什么是 goroutine?它们如何工作?
Goroutine 是由 Go 运行时管理的轻量级执行线程。与操作系统线程不同,goroutine 具有更小的栈(起始为 2 KB),并且切换速度更快。
- 启动 goroutine:
go func() - Goroutine 在同一地址空间中运行,因此访问共享数据必须同步(通过通道或互斥锁)。
package main
import ( "fmt" "time")
func printNumbers() { for i := 1; i <= 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(i) }}
func main() { go printNumbers() // 启动一个 goroutine time.Sleep(1 * time.Second) // 等待完成 fmt.Println("Main done")}重要:main 函数不会等待 goroutine 完成。如需同步,请使用 sync.WaitGroup 或通道。
3. 通道是如何工作的?
通道是类型化的“管道”,goroutine 通过它交换数据。它们提供安全的数据传输,无需显式加锁。
- 无缓冲通道:发送方会阻塞,直到接收方读取数据。
- 有缓冲通道:发送方仅在缓冲区满时阻塞。
ch := make(chan int) // 无缓冲chBuf := make(chan int, 3) // 有缓冲(容量为 3)
// 发送go func() { ch <- 42}()
// 接收value := <-chfmt.Println(value)
// 关闭通道close(ch)// 从已关闭通道读取会返回零值常见问题:从 nil 通道读取会发生什么?——答案:goroutine 会永久阻塞(死锁)。
4. Go 中的接口是什么?它们与其他编程语言有何不同?
Go 中的接口是一组方法。与 Java 或 C# 不同,Go 中接口的实现是隐式的(鸭子类型):只要类型实现了接口的所有方法,它就自动满足该接口。
type Speaker interface { Speak() string}
type Dog struct{}func (d Dog) Speak() string { return "汪!" }
type Cat struct{}func (c Cat) Speak() string { return "喵!" }
func makeSound(s Speaker) { fmt.Println(s.Speak())}
func main() { makeSound(Dog{}) // 汪! makeSound(Cat{}) // 喵!}为什么这很重要:它允许编写灵活、低耦合的代码。空接口 interface{}(或 Go 1.18+ 中的 any)可以保存任何类型的值。