勤学如春起之苗,不见其增日有所长;辍学如磨刀之石,不见其损日有所亏。

本文的重点:逃逸分析、延迟语句、散列表、通道、接口。

1.逃逸分析

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

问题描述:

有如下Go代码:

func foo() *int {
x := 1
return &x
} func main() {
p := foo()
fmt.Println(*p)
}

请问上面的代码中,变量x是否会发生逃逸?

答案解析:

在上面的代码中,变量x只在函数foo()中被定义和初始化,然后其地址被返回给了主函数main()。因为返回值是指针类型,需要在堆上分配内存,所以变量x会发生逃逸。所谓逃逸,就是指变量的生命周期不仅限于函数栈帧,而是超出了函数的范围,需要在堆上分配内存。

如果变量x没有发生逃逸,那么它会被分配在函数栈帧中,随着函数的返回而被自动销毁。而如果发生了逃逸,变量x就需要在堆上分配内存,并由垃圾回收器负责回收。在实际的程序中,大量的逃逸会导致内存分配和垃圾回收的开销增加,从而影响程序的性能。

逃逸分析是Go语言的一项优化技术,可以在编译期间分析代码,确定变量的生命周期和分配位置,从而避免不必要的内存分配和垃圾回收。通过逃逸分析的优化,可以有效地提高程序的性能和可靠性。

更多逃逸分析的内容,可以阅读我之前分享的文章:内存分配和逃逸分析详解

2.延迟语句

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

问题描述:

有如下Go代码:

func main() {
defer func() {
fmt.Println("defer 1")
}()
defer func() {
fmt.Println("defer 2")
}()
fmt.Println("main")
}

请问上面的代码中,输出的顺序是什么?

答案解析:

在上面的代码中,我们定义了两个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代码:

func main() {
m := make(map[int]string)
m[1] = "a"
m[2] = "b"
fmt.Println(m[1], m[2])
delete(m, 2)
fmt.Println(m[2])
}

请问上面的代码中,输出的结果是什么?

答案解析:

在上面的代码中,我们使用make函数创建了一个map,然后向其中添加了两个键值对,分别是1:"a"和2:"b"。接着,我们输出了这两个键对应的值,分别是"a"和"b"。

接下来,我们使用delete函数从map中删除了键为2的元素。然后,我们尝试输出键为2的值,但是输出为空。这是因为我们已经从map中删除了键为2的元素,所以它对应的值已经不存在了。

需要注意的是,当我们从map中访问一个不存在的键时,它会返回该值类型的零值。在本例中,值的类型是string,它的零值是""。所以,当我们尝试输出键为2的值时,它返回的是空字符串。

需要提醒的是,map是一种引用类型的数据结构,它的底层实现是一个哈希表。在使用map时,需要注意以下几点:

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

4.通道Channel

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

问题描述:

有如下Go代码:

func main() {
ch := make(chan int)
go func() {
ch <- 1
ch <- 2
ch <- 3
close(ch)
}()
for {
n, ok := <-ch
if !ok {
break
}
fmt.Println(n)
}
fmt.Println("done")
}

请问上面的代码中,输出的结果是什么?

答案解析:

在上面的代码中,我们使用make函数创建了一个整型通道ch。然后,我们启动了一个goroutine,向通道中写入了三个整数1、2和3,并在最后使用close函数关闭了通道。

接着,在主函数中,我们使用for循环不断从通道中读取数据,直到通道被关闭。每次从通道中读取到一个整数后,我们将它输出。最后输出"done",表示所有的数据已经读取完毕。

因为通道是一种同步的数据传输方式,写入和读取会阻塞直到对方准备好,所以输出的结果应该是:

需要注意的是:在通道被关闭后,读取操作仍然可以从通道中读取到之前写入的数据。这是因为通道中的数据并没有立即消失,而是在读取完毕后被垃圾回收器回收。因此,在使用通道时,需要根据实际情况判断何时关闭通道,以避免出现不必要的竞态和内存泄漏。

5.接口

Go语言中的接口(interface)是一种非常重要的特性,用于定义一组方法。下面是一道涉及接口的面试题及其详解。

问题描述:

有如下Go代码:

type Animal interface {
Speak() string
} type Dog struct{} func (d *Dog) Speak() string {
return "Woof!"
} type Cat struct{} func (c *Cat) Speak() string {
return "Meow!"
} func main() {
animals := []Animal{&Dog{}, &Cat{}}
for _, animal := range animals {
fmt.Println(animal.Speak())
}
}

请问上面的代码中,输出的结果是什么?

答案解析:

在上面的代码中,我们定义了一个Animal接口,它有一个Speak方法。然后,我们定义了Dog和Cat两个结构体,分别实现了Animal接口的Speak方法。

接着,在main函数中,我们创建了一个Animal类型的切片,其中包含了一个Dog对象和一个Cat对象。然后,我们使用for循环遍历这个切片,调用每个对象的Speak方法,并输出它们返回的字符串。

因为Dog和Cat都实现了Animal接口的Speak方法,所以它们都是Animal类型的对象,可以被放入Animal类型的切片中。在遍历切片时,我们调用每个对象的Speak方法,它们分别返回"Woof!"和"Meow!",然后被输出。

因此,输出的结果应该是:



需要注意的是,接口是一种动态类型,它可以包含任何实现了它所定义的方法集的类型。在使用接口时,需要注意以下几点:

  1. 接口是一种引用类型的数据结构,它的值可以为nil。
  2. 实现接口的类型必须实现接口中所有的方法,否则会编译错误。
  3. 接口的值可以赋给实现接口的类型的变量,反之亦然。
  4. 在实现接口的类型的方法中,可以通过类型断言来判断接口值的实际类型和值。

总结

这篇文章总结了5个知识点的面试题:逃逸分析、延迟语句defer、散列表map、通道Channel、接口interface

下一篇文章计划分享的5个知识点是:unsafe、context、错误处理、计时器、反射。

欢迎大家三连支持一波,你的点赞、分享,是我更文的最大动力。

公众号:程序员升职加薪之旅

「刷起来」Go必看的进阶面试题详解的更多相关文章

  1. 「万字图文」史上最姨母级Java继承详解

    摘要:继承是面向对象软件技术中的一个概念.它使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用. 本文分享自华为云社区<「万字图文」史上最姨母级Java继承详解丨[奔跑吧!JAVA] ...

  2. 「SAP技术」SAP 如何看序列号被包在哪些HU里?

    「SAP技术」SAP 如何看序列号被包在哪些HU里? 事务代码SE16 ,表名OBJK, 输入物料号,序列号,HeadTable 输入值SER06, 查询结果如下, 根据objlist, 去表ser0 ...

  3. 「建议心心」要就来15道多线程面试题一次爽到底(1.1w字用心整理)

    . 本文是给**「建议收藏」200MB大厂面试文档,整理总结2020年最强面试题库「CoreJava篇」**写的答案,所有相关文章已经收录在码云仓库:https://gitee.com/bingqil ...

  4. 「刷题」Color 群论

    这道题乍一看挺水的,直接$ Ploya $就可以了,可是再看看数据范围:n<=1e9 那就是有1e9种置换,这不歇比了. 于是考虑式子的优化. 首先证明,转i次的置换的每个循环结大小是 $ gc ...

  5. 「刷题」THUPC泛做

    刷了一下,写一下. T1. 天天爱射击 可以这样想. 我们二分一下每一块木板在什么时刻被击碎. 然后直接用主席树维护的话是\(O(nlog^2n)\)的. 会\(T\),而且是一分不给那种... 那么 ...

  6. 「LibreOJ#516」DP 一般看规律

    首先对于序列上一点,它对答案的贡献只有与它的前驱和后驱(前提颜色相同)构成的点对, 于是想到用set维护每个颜色,修改操作就是将2个set暴力合并(小的向大的合并),每次插入时更新答案即可 颜色数要离 ...

  7. 「刷题」JZPKIL

    这道反演题,真牛逼. 以下用$B$代表伯努利数,$l*g=f$代表狄利克雷卷积,先推式子. 对于给出的$n,x,y$求一百组数据的$ans$ $\begin{array}{rcl} ans & ...

  8. 「刷题」GERALD07加强版

    是LCT了. 首先我们不知道联通块怎么数. 然后颓标签知道了是LCT. 那么考虑一下怎么LCT搞. 有一个很普遍的思路大家也应该都知道,就是如何求一个区间中某种颜色的个数. 这个可以很简单的用主席树来 ...

  9. 「刷题」Triple

    正解是普通型母函数+FFT. 才学了多项式,做了一道比较好的题了. 首先有三个斧子被偷了. 我们考虑构造一种普通型母函数. 就是说一种多项式吧,我的理解. 系数是方案,下标,也就是所谓的元指数代表的是 ...

  10. 「刷题」xor

    说实话这道题没有A掉,不过所有的思路都是我自己想的,我觉得这个思路真的很棒很棒很棒的. 首先这个题的题面描述告诉我这种运算有封闭性,满足结合律和交换率,那么其实这个东西是个群运算了,而且这个群有单位元 ...

随机推荐

  1. 机器学习实战—搭建BP神经网络实现手写数字识别

    看了几天的BP神经网络,总算是对它有一点点的理解了.今天就用python搭建了一个模型来实现手写数字的识别. 一.BP神经网络简介 BP(back propagation)神经网络是一种按照误差逆向传 ...

  2. #科技 #资讯 #生活 微信测试更多图片打开方式,神州圆满发射,英伟达或停产性价比神卡,SAMSUNG新一代显存带宽容量双翻倍,这就是今天的其它大新闻

    今天是2022年12月01日 十一月初八 现在是中午12:10 下面是今天的其他大新闻 #NEWS 1 # 微信测试用不同小程序打开图片:快捷调用小程序打开图片.视频.文件 ( 新浪科技 ) 据悉,微 ...

  3. 微信小程序主包和分包的资源可以相互引用吗

    了解主包.分包 整个小程序所有分包大小不超过20M;单个分包/主包大小不能超过 2M 主包: a. 放置默认启动页面&&tabBar页面, 以及一些分包需要用到的公共资源(如wxss. ...

  4. .net core 接收并存储客户端上传的文件

    1 文件是上传到Host,非上传到阿里云OSS 2 在Program.cs或StartUp中使用静态文件的中间件 public void Configure(IApplicationBuilder a ...

  5. GPS数据处理

    GPS数据处理 题目内容: NMEA-0183协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The Nationa ...

  6. springboot项目启动报错:找不到或无法加载主类 com....

    springboot项目报错 找不到或无法加载主类 com.... 1.如果是导入的别人的项目 首先要配置好JDK 和 MAVEN 然后点击右侧栏的maven图标 --->点击clean(清除掉 ...

  7. jsp第九周作业

    1.做一个图书类Book id,name,price ,get,set访问器,构造方法2个,1个无参,1个有参做一个测试类,在main中创建3个图书对象,放到list集合中.做一个菜单,可以添加,删除 ...

  8. 安装labelme

    按照下面指令安装 conda create --name=labelme python3.6(根据下载的python版本而定) activate labelme conda install pyqt ...

  9. C语言初级阶段5——函数1

    C语言初级阶段5--函数1 函数的基本概念 1.函数:理解为封装功能的容器. 主函数是函数的入口 2.函数定义的基本格式: 返回值类型:常用的基本数据类型,执行完以后,函数会得到一个什么类型的值,如果 ...

  10. Jenkins系列(1)-离线安装插件

    插件地址:http://updates.jenkins-ci.org/download/plugins/