尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

三个 Go 基础问题,帮你筛掉 90% 的“资深工程师”

三个 Go 基础问题,帮你筛掉 90% 的“资深工程师” 大多数开发者能聊一下午微服务。但这三个问题能看出他们是否真的理解 Go。几年前我在面试一位 Go 后端开发候选人。简历很漂亮“5 年 Go 经验”、“设计过高并发系统”、“精通微服务架构”。然后我问了一个简单的问题“Go 的make和new有什么区别”沉默。一段很长的沉默。然后是一个经典回答“make用来创建切片new用来创建结构体……差不多吧。”差不多在 Go 里“差不多”通常意味着“不清楚”。那次面试让我意识到一件事很多开发者成了框架、云平台和架构图的专家但真正理解 Go 运行时和语言底层机制的人比想象中少得多。如果我只用 15 分钟评估一位 Go 开发者以下三个问题就够了。它们的效果出奇地好。1.make和new到底有什么区别这个问题听起来基础实则不然。大多数开发者会立即说“new分配内存make初始化切片、map 和 channel。”这是对的但只是表面。然后我会追问“那new返回什么make返回什么”new(T)返回的是*T——一个指向类型 T 的零值指针。它只分配内存不进行任何初始化。make(T, ...)只用于slice、map和channel返回的是T本身不是指针并且会进行内部结构的初始化。p:new([]int)// p 是 *[]int指向 nil 切片s:make([]int,5)// s 是 []int一个长度 5、容量 5 的切片如果有人说“new和make差不多”说明他们可能没真正处理过零值设计和类型系统。还有一个更犀利的问题“那var s []int和make([]int, 0)有什么区别”var s []int声明了一个 nil 切片不分配内存make([]int, 0)分配了一个空切片长度和容量都为 0它不为 nil。两者的行为在 JSON 序列化、append和len上都有细微差异。为什么这很重要因为 Go 的零值设计贯穿整个语言。不理解make和new就很难理解 Go 的“零值可用”哲学也容易写出隐含的内存分配问题。2.defer的求值时机和参数捕获这个问题一下子就能看出一个人是否真的在 Go 里调试过生产问题。代码很简单funcmain(){i:0deferfmt.Println(i)i}输出是什么是0。因为defer语句在声明时就对参数求值而不是在调用时。然后我会继续问“那如果改成闭包呢”funcmain(){i:0deferfunc(){fmt.Println(i)}()i}输出是1因为闭包捕获的是变量引用。再问一个“下面这段代码有什么问题”funcreadFile(){f,err:os.Open(file.txt)deferf.Close()// 处理文件...}如果os.Open失败f为nildefer f.Close()会引发 panic。很多“资深工程师”会写这样的代码因为在其他语言里这种模式是安全的。但 Go 不是其他语言。理解defer的求值时机、参数传递方式和 nil 检查是写出健壮生产代码的基础。3. 什么情况下channel会阻塞这个问题考察的是对 Go 并发模型的理解深度。我会先给一段代码ch:make(chanint)ch-42这段代码会死锁。因为无缓冲 channel 的发送和接收必须同时准备好。然后我会问“那make(chan int, 1)呢还会阻塞吗”发送不会阻塞因为缓冲区有空间。但如果再发一次没有接收者就会阻塞。接着我会追问“什么情况下从channel读取会阻塞”空 channel 读会阻塞。但如果channel被关闭了呢读取会立即返回零值。ch:make(chanint)close(ch)v:-ch// v 0不会阻塞然后我会问一个真正有区分度的问题“for range遍历channel什么时候会退出”答案是当channel被关闭且所有值都被读取后。如果channel没有被关闭for range会一直阻塞。到这里大部分人的信心已经出现了裂缝。最后我会追问“如果多个 goroutine 同时向一个无缓冲 channel 发送但只有一个接收者会发生什么”只有第一个发送会与接收者匹配其余发送会阻塞直到有新的接收者出现。这是 Go 的“无缓冲 channel 是同步的”这一特性的直接体现。这些问题的共同点这三个问题make和new的区别defer的求值时机和参数捕获各种场景下channel的阻塞规则它们有个共同点来自官方 FAQ 和常见误区的精炼。每一个都有明确的官方文档解释。它们考察的不是知识点而是对 Go 运行时行为的真实理解。一个高级工程师不一定能设计出完美的微服务架构但一定能准确说出defer的求值时机。因为后者的理解决定了前者的代码在凌晨三点会不会出问题。为什么现代面试容易失效很多 Go 面试变成了框架问答“Gin 怎么用”、“GORM 的钩子怎么写”、“如何配置 Viper”这些问题有价值但框架每两年换一轮。基础不会。一个真正理解内存模型、并发原语、接口语义的工程师可以学习任何框架。反之则不然。我见过能一天搭出完整 HTTP 服务的开发者却说不清select在多个channel就绪时的行为。那不是能力问题。那是基础认知问题。最后我认为“资深”不是按年限划分的。我见过 10 年经验的工程师把同一年的经验重复了 10 次。也见过 3 年经验的开发者对 Go 的调度器模型如数家珍。区别在于好奇心。最好的 Go 工程师总是在问“这下面发生了什么”那些人是解决最难生产问题的人。所以这三个问题你能自信回答吗如果不能不用太担心。大多数人都不能。而这正是它们值得被研究的原因。
返回列表