Web前端最全【狂刷面试题】GO常见面试题汇总_go面试题(2),推荐程序员面试秘籍是什么

最后

今天的文章可谓是积蓄了我这几年来的应聘和面试经历总结出来的经验,干货满满呀!如果你能够一直坚持看到这儿,那么首先我还是十分佩服你的毅力的。不过光是看完而不去付出行动,或者直接进入你的收藏夹里吃灰,那么我写这篇文章就没多大意义了。所以看完之后,还是多多行动起来吧!

可以非常负责地说,如果你能够坚持把我上面列举的内容都一个不拉地看完并且全部消化为自己的知识的话,那么你就至少已经达到了中级开发工程师以上的水平,进入大厂技术这块是基本没有什么问题的了。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】


来判断。


原因是:**一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0。但是我们不能说一个长度和容量都是0的切片一定是nil。**


我们通过下面的示例就很好理解了:



var s1 []int //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{} //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil


所以要判断一个切片是否是空的,要是用len(s) == 0来判断,不应该使用s == nil来判断。


其根本原因在于后面两种初始化方式已经给切片分配了空间,所以就算切片为空,也不等于nil。但是len(s) == 0成立,则切片一定为空。


注意:**在go中 var是声明关键字,不会开辟内存空间;使用 := 或者 make 关键字进行初始化时才会开辟内存空间。**


## 深拷贝和浅拷贝


### 操作对象


深拷贝和浅拷贝操作的对象都是Go语言中的引用类型


### 区别如下:


引用类型的特点是在内存中存储的是其他值的内存地址;而值类型在内存中存储的是真实的值。


我们在go语言中通过 := 赋值引用类型就是 浅拷贝,即拷贝的是内存地址,两个变量对应的是同一个内存地址对应的同一个值。



a := []string{1,2,3}
b := a


如果我们通过copy()函数进行赋值,就是深拷贝,赋值的是真实的值,而非内存地址,会在内存中开启新的内存空间。


举例如下:



a := []string{1,2,3}
b := make([]string,len(a),cap(a))
copy(b,a)


## new和make


### new


new是GO语言一个内置的函数,它的函数签名如下:



func new(Type) *Type


#### 特点


* Type表示类型,new函数只接受一个参数,这个参数是一个类型
* \*Type表示类型指针,new函数返回一个指向该类型内存地址的指针。


new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。


#### 举个例子:



func main() {
a := new(int)
b := new(bool)
fmt.Printf(“%T\n”, a) // *int
fmt.Printf(“%T\n”, b) // *bool
fmt.Println(*a) // 0
fmt.Println(*b) // false
}


#### 使用技巧


var a \*int只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。


应该按照如下方式使用内置的new函数对a进行初始化之后就可以正常对其赋值了:



func main() {
var a *int
a = new(int)
*a = 10
fmt.Println(*a)

}


### make


make也是用于内存分配的,区别于new,它只用于slice、map以及channel的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型(指针类型),所以就没有必要返回他们的指针了。


#### make函数的函数签名



func make(t Type, size …IntegerType) Type


### 特点


make函数是无可替代的,我们在使用slice、map以及channel的时候,都需要使用make进行初始化,然后才可以对它们进行操作。


### 使用技巧


`var b map[string]int`这段代码,只是声明变量b是一个map类型的变量,需要像下面的示例代码一样使用make函数进行初始化操作之后,才能对其进行键值对赋值:



func main() {
var b map[string]int
b = make(map[string]int, 10)
b[“分数”] = 100
fmt.Println(b)
}


### 总结:new与make的区别


1. 二者都是用来做内存分配的。
2. make只用于slice、map以及channel的初始化,返回的是类型本身(类型本身就是引用类型(指针类型));
3. 而new用于内存分配时,在内存中存储的是对应类型的型零值(比如0,false),返回的是该类型的指针类型。


## go的map实现排序


我们知道go语言的map类型底层是有hash实现的,是无序的,不支持排序。


如果我们的数据使用map类型存储,如何实现排序呢?


### 解决思路


排序map的key,再根据排序后的key遍历输出map即可。


### 代码实现:



package main

import (
“fmt”
“math/rand”
“sort”
“time”
)

func main() {
rand.Seed(time.Now().UnixNano()) //初始化随机数种子

var scoreMap = make(map[string]int, 30)

for i := 0; i < 30; i++ {
key := fmt.Sprintf(“stu%02d”, i) //生成stu开头的字符串
value := rand.Intn(30) //生成0~50的随机整数
scoreMap[key] = value
}
//取出map中的所有key存入切片keys
var keys = make([]string, 0, 30)
for key := range scoreMap {
keys = append(keys, key)
}
//对切片进行排序
sort.Strings(keys)
//按照排序后的key遍历map
for _, key := range keys {
fmt.Println(key, scoreMap[key])
}
}


### 运行结果


![](https://img-blog.csdnimg.cn/img_convert/913de6676bf9d90429aad954fc060e1b.webp?x-oss-process=image/format,png)


### 逃逸分析


我们在上面有提到堆和栈的概念,在go中逃逸分析是一个重要的概念,需要大家理解。


正如我们上面提到的,内存分配既可以分配到堆中,也可以分配到栈中。



> 
> 那么什么样的数据会分配到栈中,什么数据又会被分配到堆中呢?GO语言是如何进行内存分配的呢?其设计初衷和实现原理是什么呢?
> 
> 
> 


### 内存管理


内存管理主要包括两个动作:分配与释放。逃逸分析就是服务于内存分配,为了更好理解逃逸分析,我们再来回顾一下堆栈的特点:


### 栈


在Go中,栈的内存是由编译器自动进行分配和释放,栈区往往存储着函数参数、局部变量和调用函数帧,它们随着函数的创建而分配,函数的退出而销毁。一个goroutine对应一个栈,栈是调用栈(call stack)的简称。一个栈通常又包含了许多栈帧(stack frame),它描述的是函数之间的调用关系,每一帧对应一次尚未返回的函数调用,它本身也是以栈形式存放数据。


### 堆


与栈不同的是,应用程序在运行时只会存在一个堆。我们可以简单理解为:**我们在GO开发过程中要考虑的内存管理只是针对堆内存而言的。** 程序在运行期间可以主动从堆上申请内存,这些内存通过Go的内存分配器分配,并由垃圾收集器回收。


### 堆和栈的对比


#### 加锁


* 栈是每个goroutine独有的,这就意味着栈上的内存操作是不需要加锁的。
* 堆上的内存,有时需要加锁防止多线程冲突(为什么要说有时呢?因为Go的内存分配策略学习了TCMalloc的线程缓存思想,他为每个处理器P分配了一个mcache,从mcache分配内存也是无锁的)。


#### 性能


* 堆内存管理 性能差:对于程序堆上的内存回收,还需要通过标记清除阶段,例如Go采用的三色标记法。
* 栈内存管理 性能好:栈上的内存,它的分配与释放非常廉价。简单地说,它只需要两个CPU指令:一个是分配入栈,另外一个是栈内释放。只需要借助于栈相关寄存器即可完成。


#### 缓存策略


栈内存能更好地利用CPU的缓存策略,因为栈空间相较于堆来说是更连续的。


### 逃逸分析




### 最后

**前端CSS面试题文档,JavaScript面试题文档,Vue面试题文档,大厂面试题文档**

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)**

![](https://img-blog.csdnimg.cn/img_convert/54102d41aa331f26e2e6db4296123d3f.webp?x-oss-process=image/format,png)

![](https://img-blog.csdnimg.cn/img_convert/a5cda75d1eb27e6f4d418a588a19a6a4.webp?x-oss-process=image/format,png)



内存能更好地利用CPU的缓存策略,因为栈空间相较于堆来说是更连续的。


### 逃逸分析




### 最后

**前端CSS面试题文档,JavaScript面试题文档,Vue面试题文档,大厂面试题文档**

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)**

[外链图片转存中...(img-sOVqwnav-1715877593183)]

[外链图片转存中...(img-HfHZIRWp-1715877593183)]



  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值