GO必知必会的常见面试题汇总

作者:王中阳Go 时间:2023-07-14 01:47:07 

引言

今年互联网的就业环境真的好糟糕啊,好多朋友被优化。

我们平常在工作中除了撸好代码,跑通项目之外,还要注意内外兼修。内功和招式都得练👌,才能应对突如其来的变故,顺利的拿到新的offer,不要问我怎么知道的。

这个月我会整理分享一系列后端工程师求职面试相关的文章,知识脉络图如下:

  • JAVA/GO/PHP 面试常问的知识点

  • DB:MySql PgSql

  • Cache: Redis MemCache MongoDB

  • 数据结构

  • 算法

  • 微服务&高并发

  • 流媒体

  • WEB3.0

  • 源码分析

通过这一系列的文章,大家不仅能温习和梳理后端开发相关的知识点,也可以了解目前的市场环境对服务端开发,尤其是对Go开发工程师的岗位要求,需要掌握哪些核心技术。

值类型和引用类型

值类型有哪些?

基本数据类型都是值类型,包括:int系列、float系列、bool、字符串、数组、结构体struct。

引用类型有哪些?

指针、切片slice、接口interface、管道channel

值类型和引用类型的区别?

  • 值类型在内存中存储的是值本身,而引用类型在内存中存储的是值的内存地址。

  • 值类型内存通常在栈中分配,引用类型内存通常在堆中分配。

垃圾回收

引用类型的内存在堆中分配,当没有任何变量引用堆中的内存地址时,该内存地址对应的数据存储空间就变成了垃圾,就会被GO语言的GC回收。

一图胜千言

GO必知必会的常见面试题汇总

GO必知必会的常见面试题汇总

堆和栈

在Go中,栈的内存是由编译器自动进行分配和释放,栈区往往存储着函数参数、局部变量和调用函数帧,它们随着函数的创建而分配,函数的退出而销毁。

一个goroutine对应一个栈,栈是调用栈(call stack)的简称。一个栈通常又包含了许多栈帧(stack frame),它描述的是函数之间的调用关系,每一帧对应一次尚未返回的函数调用,它本身也是以栈形式存放数据。

与栈不同的是,应用程序在运行时只会存在一个堆。狭隘地说,内存管理只是针对堆内存而言的。程序在运行期间可以主动从堆上申请内存,这些内存通过Go的内存分配器分配,并由垃圾收集器回收。

切片

比较

切片之间是不能比较的,我们不能使用==操作符来判断两个切片是否含有全部相等元素。

切片唯一合法的比较操作是和nil比较。

比较的详解

要检查切片是否为空,应该使用

len(s) == 0

来判断,而不应该使用

s == nil

来判断。

原因是:一个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的区别

  • 二者都是用来做内存分配的。

  • make只用于slice、map以及channel的初始化,返回的是类型本身(类型本身就是引用类型(指针类型));

  • 而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])
  }
}

运行结果

GO必知必会的常见面试题汇总

逃逸分析

逃逸分析比较硬核,单独写了一篇文章:# 【狂刷面试题】Go逃逸分析详解

最后,听我说

不用好奇我为什么会出这个系列的文章,没错,我最近处于失业状态,所以掘金也断更了好久,疲于奔命的在为拿到新offer而奋斗,好在花了2周的时间拿到了新的offer。

在此衷心的劝诫各位小伙伴:如果你对你的工作不满意,请三思再三思之后再离职,尤其不要傲娇的裸辞。

如果你的公司或者你的部门发展的还不错,请你加倍珍惜这份工作,踏踏实实,为公司发光发热,贡献力量,把不断学习的口号转化成落地输出的行动,真真正正的做到肉眼可见的提高。

如果你也和我一样不幸被离职,请不要沮丧更不要抱怨,快速调整负面情绪,进一步提升自己才是王道。

福祸相依:祸兮福之所倚,福兮祸之所伏。

暂时的失意放在人生的长河中算不上什么,我们要做的应该是尽快收拾起行囊,朝着下一个更美好的前方走去,哪怕路上会磕磕绊绊,但是我们一定会抬足向前。

来源:https://juejin.cn/post/7131717990558466062

标签:GO,面试题,面试
0
投稿

猜你喜欢

  • Python的Pillow库进行图像文件处理(图文详解)

    2023-10-04 04:02:23
  • 如何在vue中使用ant-design-vue组件

    2024-05-02 16:32:47
  • 提高MySQL数据库查询效率的几个技巧

    2009-01-19 12:52:00
  • Django如何实现上传图片功能

    2023-04-23 17:35:01
  • 浅谈python多线程和多线程变量共享问题介绍

    2022-08-29 04:34:18
  • Python的gevent框架的入门教程

    2023-06-26 16:58:34
  • python实现生成Word、docx文件的方法分析

    2021-03-01 07:49:53
  • python中with用法讲解

    2022-11-29 23:59:37
  • C#命名空间System.ComponentModel属性方法汇总

    2024-06-05 09:24:02
  • Oracle 数据库操作类

    2009-08-12 12:06:00
  • mysql 5.7.16 安装配置方法图文教程

    2024-01-28 14:26:32
  • 网马解密大讲堂——网马解密中级篇(Eval篇)

    2009-09-16 16:04:00
  • 五个小窍门帮你写出更好的CSS代码

    2009-06-09 12:42:00
  • 基于Python实现牛牛套圈小游戏的示例代码

    2022-04-04 03:50:23
  • Go并发同步Mutex典型易错使用场景

    2024-05-02 16:23:54
  • Python Numpy中数组的集合操作详解

    2023-12-04 12:02:24
  • 微信小程序(六):列表上拉加载下拉刷新示例

    2024-05-11 09:34:22
  • 详解Python中的相对导入和绝对导入

    2023-02-05 01:10:36
  • PHP文件操作详解

    2023-11-20 07:44:25
  • SQL Server 服务器优化技巧浅谈

    2024-01-13 17:31:01
  • asp之家 网络编程 m.aspxhome.com