「刷起来」Go必看的进阶面试题详解

打印 上一主题 下一主题

主题 976|帖子 976|积分 2928

勤学如春起之苗,不见其增日有所长;辍学如磨刀之石,不见其损日有所亏。
本文的重点:逃逸分析、延迟语句、散列表、通道、接口。
1.逃逸分析

逃逸分析是Go语言中的一项重要优化技术,可以帮助程序减少内存分配和垃圾回收的开销,从而提高程序的性能。下面是一道涉及逃逸分析的面试题及其详解。
问题描述:

有如下Go代码:
  1. func foo() *int {
  2.     x := 1
  3.     return &x
  4. }
  5. func main() {
  6.     p := foo()
  7.     fmt.Println(*p)
  8. }
复制代码
请问上面的代码中,变量x是否会发生逃逸?
答案解析:

在上面的代码中,变量x只在函数foo()中被定义和初始化,然后其地址被返回给了主函数main()。因为返回值是指针类型,需要在堆上分配内存,所以变量x会发生逃逸。所谓逃逸,就是指变量的生命周期不仅限于函数栈帧,而是超出了函数的范围,需要在堆上分配内存。
如果变量x没有发生逃逸,那么它会被分配在函数栈帧中,随着函数的返回而被自动销毁。而如果发生了逃逸,变量x就需要在堆上分配内存,并由垃圾回收器负责回收。在实际的程序中,大量的逃逸会导致内存分配和垃圾回收的开销增加,从而影响程序的性能。
逃逸分析是Go语言的一项优化技术,可以在编译期间分析代码,确定变量的生命周期和分配位置,从而避免不必要的内存分配和垃圾回收。通过逃逸分析的优化,可以有效地提高程序的性能和可靠性。
更多逃逸分析的内容,可以阅读我之前分享的文章:内存分配和逃逸分析详解
2.延迟语句

defer语句是Go语言中的一项重要特性,可以用于在函数返回前执行一些清理或收尾工作,例如释放资源、关闭连接等。下面是一道涉及defer语句的面试题及其详解。
问题描述:

有如下Go代码:
  1. func main() {
  2.     defer func() {
  3.         fmt.Println("defer 1")
  4.     }()
  5.     defer func() {
  6.         fmt.Println("defer 2")
  7.     }()
  8.     fmt.Println("main")
  9. }
复制代码
请问上面的代码中,输出的顺序是什么?
答案解析:

在上面的代码中,我们定义了两个defer语句,它们分别输出"defer 1"和"defer 2"。这两个defer语句的执行顺序是先进后出的,也就是说后定义的defer语句先执行,先定义的defer语句后执行。因此,输出的顺序应该是"main"、"defer 2"、"defer 1"。
这个例子也展示了defer语句的另一个特性,即在函数返回前执行。在main函数返回前,两个defer语句分别执行了它们的函数体,输出了相应的内容。这种特性可以用于释放资源、关闭连接等操作,在函数返回前保证它们被执行。
需要注意的是,defer语句并不是一种异步操作,它只是将被延迟执行的函数加入到一个栈中,在函数返回前按照后进先出的顺序执行。因此,在defer语句中的函数应该是轻量级的,避免影响程序的性能。同时,也需要注意defer语句的执行顺序和函数返回时的状态,避免出现不符合预期的结果。
3.散列表Map

Go语言中的map是一种非常有用的数据结构,可以用于存储键值对。下面是一道涉及map的面试题及其详解。
问题描述:

有如下Go代码:
  1. func main() {
  2.     m := make(map[int]string)
  3.     m[1] = "a"
  4.     m[2] = "b"
  5.     fmt.Println(m[1], m[2])
  6.     delete(m, 2)
  7.     fmt.Println(m[2])
  8. }
复制代码
请问上面的代码中,输出的结果是什么?
答案解析:

在上面的代码中,我们使用make函数创建了一个map,然后向其中添加了两个键值对,分别是1:"a"和2:"b"。接着,我们输出了这两个键对应的值,分别是"a"和"b"。
接下来,我们使用delete函数从map中删除了键为2的元素。然后,我们尝试输出键为2的值,但是输出为空。这是因为我们已经从map中删除了键为2的元素,所以它对应的值已经不存在了。
需要注意的是,当我们从map中访问一个不存在的键时,它会返回该值类型的零值。在本例中,值的类型是string,它的零值是""。所以,当我们尝试输出键为2的值时,它返回的是空字符串。
需要提醒的是,map是一种引用类型的数据结构,它的底层实现是一个哈希表。在使用map时,需要注意以下几点:

  • map是无序的,即元素的顺序不固定。
  • map的键必须是可以进行相等性比较的类型,如int、string、指针等。(通俗来说就是可以用==和!=来比较的,除了slice、map、function这几个类型都可以)
  • map的值可以是任意类型,包括函数、结构体等。
  • 在多个goroutine之间使用map时需要进行加锁,避免并发访问导致的竞态问题。
4.通道Channel

Go语言中的通道(channel)是一种非常有用的特性,用于在不同的goroutine之间传递数据。下面是一道涉及通道的面试题及其详解。
问题描述:

有如下Go代码:
[code]func main() {    ch := make(chan int)    go func() {        ch
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊雷无声

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表