GO面试一定要看看这些面试题

news2025/8/11 14:10:20

Go核心特性

1.goroutine

协程是用户态轻量级线程,它是线程调度的基本单位

使用者分配足够多的任务,系统能自动帮助使用者把任务分配到 CPU 上,让这些任务尽量并发运作。这种机制在 Go语言中被称为 goroutine(协程)。

2.channel

Don’t communicate by sharing memory, share memory by communicating.

channel是go语言协程中数据通信的双向通道。但是在实际应用中,为了代码的简单和易懂,一般使用的channel是单向的。

img

缓冲机制

有缓冲

package main

import "fmt"

/*有缓冲*/
func main() {
	ch := make(chan int, 3)//缓冲区大小为3,消息个数小于等于3都不会阻塞goroutine
	ch <- 1
	fmt.Println(<-ch)//输出1
	ch <- 2
	fmt.Println(<-ch)//输出2
	ch <- 3
	ch <- 4
	fmt.Println(len(ch))//输出2,表示是channel有两个消息
	fmt.Println(cap(ch))//输出3,表示缓存大小总量为3
}

无缓冲

package main

import "fmt"

/*无缓冲*/
func main() {
	ch := make(chan int, 3)
	ch <- 2
	ch <- 1
	ch <- 3
	elem := <-ch
	fmt.Println("The first element received from channel ch:%v\n", elem)
}

3.defer

defer执行顺序和调用顺序相反,类似于栈先进后出。

defer一般用于资源的释放和异常的捕捉, 作为Go语言的特性之一.

defer 语句会将其后面跟随的语句进行延迟处理. 意思就是说 跟在defer后面的语言 将会在程序进行最后的return之后再执行.

在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。

4.切片

5.垃圾回收机制

6.int与int32

go语言中的int的大小是和操作系统位数相关的,如果是32位操作系统,int类型的大小就是4字节。如果是64位操作系统,int类型的大小就是8个字节。除此之外uint也与操作系统有关。

int8占1个字节,int16占2个字节,int32占4个字节,int64占8个字节。

7.interface代替继承多态

8.字母大小设置可见性

9.没有模板泛型

10.所有类型初始化默认为0

11.反射

底层实现

切片(slice)和数组的区别

切片数组
长度可以不断增加但不会减少初始化确定数组的长度
长度可变长度固定、值传递
底层实现数组每个数据的引用、指针,自身是结构体函数参数传递需要制定数组长度

make与new的区别

makenew
make只用于给slice、map、channel类(引用类型)分配内存,返回对应的类型,并非指针new用于各种类型的内存分配,返回指针,指向对应类型的零值 类型的指针需要分配内存才能赋值,与c中一样

并发编程

runtime

go运行的基础设施

  • 协调多线程调度、内存分配、GC
  • 操作系统、CPU级别操作的封装(信号处理,系统调用、寄存器操作、原子操作)、CGO
  • 性能分析等,pprof、trace、race
  • 反射实现

与python、java的runtime不同的是,在运行时与用户代码没有明显的界限,一起打包

最主要的功能是两个方面:调度、GC

调度

众所周知,操作系统内部有着线程、进程调度器,当触发阻塞、时间片用尽、硬件中断的时候,都会涉及到切换的问题

Go在此基础上实现了自己的调度器(调度Goroutine,Go内部最基本的执行单元)

线程与协程

线程:共享堆,不共享栈,其切换由操作系统控制

协程:共享堆,不共享栈,切换由程序员显式控制,可以避免上下文切换的额外消耗,可以运行在一个或多个线程上

协程的切换调度在用户空间完成,不涉及到用户空间到内核空间的切换(寄存器切换、内存数据切换、栈切换、安全检查),线程调度里面的taskstructure除了CPU信息之外,还会保存线程的私有栈以及寄存器,上下文会多一点,在POSIX中线程获得了许多进程拥有的功能,这些功能在go的调度中都是用不到的,同时也增加了开销

由于线程拥有协程,而一个线程只在一个CPU上执行,导致协程没有办法利用多核

Goroutine与协程类似,且可以实现并行

Go实现了调度器之后

  • 可以自己管理上下文切换等,减少切换成本(协程切换)
  • GC的时候需要暂停所有运行的goroutine,使得内存状态一致的时候进行垃圾回收

面试题:

=和:=的区别

=是赋值变量,:=是定义变量。

指针的作用

个指针可以指向任意变量的地址,它所指向的地址在32位或64位机器上分别固定占4或8个字节。指针的作用有:

  • 获取变量的值
 import fmt
 
 func main(){
  a := 1
  p := &a//取址&
  fmt.Printf("%d\n", *p);//取值*
 }
  • 改变变量的值
 // 交换函数
 func swap(a, b *int) {
     *a, *b = *b, *a
 }
  • 用指针替代值传入函数,比如类的接收器就是这样的。
 type A struct{}
 
 func (a *A) fun(){}

持久化是怎么做的

所谓持久化就是将要保存的字符串写到硬盘等设备。

  • 最简单的方式就是采用ioutil的WriteFile()方法将字符串写到磁盘上,这种方法面临格式化方面的问题。

  • 更好的做法是将数据按照固定协议进行组织再进行读写,比如JSON,XML,Gob,csv等。

  • 如果要考虑高并发高可用,必须把数据放入到数据库中,比如MySQL,PostgreDB,MongoDB等。

    磁盘——》固定协议——》数据库(高并发高可用)

简述Go语言GC(垃圾回收)的工作原理

标记清楚法

分为两个阶段:标记和清除

标记阶段:从根对象出发寻找并标记所有存活的对象。

清除阶段:遍历堆中的对象,回收未标记的对象,并加入空闲链表。

缺点是需要暂停程序STW。

三色标记法

将对象标记为白色,灰色或黑色。

白色:不确定对象(默认色);黑色:存活对象。灰色:存活对象,子对象待处理。

标记开始时,先将所有对象加入白色集合(需要STW)。首先将根对象标记为灰色,然后将一个对象从灰色集合取出,遍历其子对象,放入灰色集合。同时将取出的对象放入黑色集合,直到灰色集合为空。最后的白色集合对象就是需要清理的对象。

这种方法有一个缺陷,如果对象的引用被用户修改了,那么之前的标记就无效了。因此Go采用了写屏障技术,当对象新增或者更新会将其着色为灰色。

三色标记法+混合写屏障

❤go如何进行调度的。GMP中状态流转。

Go里面GMP分别代表:G:goroutine,M:线程(真正在CPU上跑的),P:调度器。

GMP模型

调度器是M和G之间桥梁。

go进行调度过程:

  • 某个线程尝试创建一个新的G,那么这个G就会被安排到这个线程的G本地队列LRQ中,如果LRQ满了,就会分配到全局队列GRQ中;

  • 尝试获取当前线程的M,如果无法获取,就会从空闲的M列表中找一个,如果空闲列表也没有,那么就创建一个M,然后绑定G与P运行。

  • 进入调度循环:

    • 找到一个合适的G
    • 执行G,完成以后退出

Go面向对象是如何实现的

Go实现面向对象的两个关键是struct和interface。

封装:对于同一个包,对象对包内的文件可见;对不同的包,需要将对象以大写开头才是可见的。

继承:继承是编译时特征,在struct内加入所需要继承的类即可:

type A struct{}
type B struct{
A
}

多态:多态是运行时特征,Go多态通过interface来实现。类型和接口是松耦合的,某个类型的实例可以赋给它所实现的任意接口类型的变量。

Go支持多重继承,就是在类型中嵌入所有必要的父类型。

Channel底层实现

map的底层实现

源码位于src\runtime\map.go 中。

go的map和C++map不一样,底层实现是哈希表,包括两个部分:hmapbucket

hmap结构体如图:

type hmap struct {
    count     int //map元素的个数,调用len()直接返回此值
    
    // map标记:
    // 1. key和value是否包指针
    // 2. 是否正在扩容
    // 3. 是否是同样大小的扩容
    // 4. 是否正在 `range`方式访问当前的buckets
    // 5. 是否有 `range`方式访问旧的bucket
    flags     uint8 
    
    B         uint8  // buckets 的对数 log_2, buckets 数组的长度就是 2^B
    noverflow uint16 // overflow 的 bucket 近似数
    hash0     uint32 // hash种子 计算 key 的哈希的时候会传入哈希函数
    buckets   unsafe.Pointer // 指向 buckets 数组,大小为 2^B 如果元素个数为0,就为 nil
    
    // 扩容的时候,buckets 长度会是 oldbuckets 的两倍
    oldbuckets unsafe.Pointer // bucket slice指针,仅当在扩容的时候不为nil
    
    nevacuate  uintptr // 扩容时已经移到新的map中的bucket数量
    extra *mapextra // optional fields
}

里面最重要的是buckets(桶)。buckets是一个指针,最终它指向的是一个结构体:

// A bucket for a Go map.
type bmap struct {
    tophash [bucketCnt]uint8
}

每个bucket固定包含8个key和value(可以查看源码bucketCnt=8).实现上面是一个固定的大小连续内存块,分成四部分:每个条目的状态,8个key值,8个value值,指向下个bucket的指针。

创建哈希表使用的是makemap函数.map 的一个关键点在于,哈希函数的选择。在程序启动时,会检测 cpu 是否支持 aes,如果支持,则使用 aes hash,否则使用 memhash。这是在函数 alginit() 中完成,位于路径:src/runtime/alg.go 下。

map查找就是将key哈希后得到64位(64位机)用最后B个比特位计算在哪个桶。在 bucket 中,从前往后找到第一个空位。这样,在查找某个 key 时,先找到对应的桶,再去遍历 bucket 中的 key。

GO interface的实现

go的接口由两种类型实现ifaceeface。iface是包含方法的接口,而eface不包含方法。

  • iface

​ 对应的数据结构是(位于src\runtime\runtime2.go):

type iface struct {
	tab  *itab
	data unsafe.Pointer
}

可以简单理解为,tab表示接口的具体结构类型,而data是接口的值。

itab:

type itab struct {
	inter *interfacetype //此属性用于定位到具体interface
	_type *_type //此属性用于定位到具体interface
	hash  uint32 // copy of _type.hash. Used for type switches.
	_     [4]byte
	fun   [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
}

属性interfacetype类似于_type,其作用就是interface的公共描述,类似的还有maptypearraytypechantype…其都是各个结构的公共描述,可以理解为一种外在的表现信息。interfaetype和type唯一确定了接口类型,而hash用于查询和类型判断。fun表示方法集。

  • eface

与iface基本一致,但是用_type直接表示类型,这样的话就无法使用方法。

type eface struct {
	_type *_type
	data  unsafe.Pointer
}

Go的调试和分析工具有哪些

go cover 测试代码覆盖率

go doc 用于生成go文档

pprof 用于性能调优,针对cpu、内存和并发

race 用于竞争检测

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/33787.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【javaEE】网络原理(网络层)

努力经营当下&#xff0c;直至未来明朗 文章目录前言一、网络层简述【IP协议】THINK前言 一个人最大的痛苦来源于对自己无能的愤怒 Hi&#xff0c;这里是不想秃头的宝贝儿&#xff01; 本文主要介绍【网络层】&#xff0c;其中最关键的就是【IP协议】。&#xff08;同样&…

【天池竞赛】心跳数据挖掘

天池学习赛 心跳数据挖掘 168分攻略 Chapter 1. 赛题解析 就如比赛界面所介绍的一般&#xff0c;这里再复述一遍 本次新人赛是Datawhale与天池联合发起的0基础入门系列赛事 —— 心跳信号分类预测。赛题以心电图心跳信号数据为背景&#xff0c;要求选手根据心电图感应数据预测…

【序列召回推荐】(task4)多兴趣召回实践:MIND(更新中)

note 阿里的序列召回MIND模型&#xff1a;引入了胶囊网络&#xff0c;将胶囊网络的动态路由算法引入到了用户的多兴趣建模上&#xff0c;通过B2I动态路由很好的从用户的原始行为序列中提取出用户的多种兴趣表征。在离线训练阶段&#xff0c;通过提出Label-Aware Attention详细…

Lifecycle 生命周期组件的那些事

引言 在2022的今天&#xff0c;AndroidX 普遍的情况下&#xff0c;JetPack Lifecycle 也早已经成为了开发中的基础设施&#xff0c;小到 View(扩展库) ,大到 Activity&#xff0c;都隐藏着它的身影&#xff0c;而了解 Lifecycle 也正是理解 JetPack 组件系列库生命感知设计的基…

D-013 蜂鸣器硬件电路设计

蜂鸣器硬件电路设计1 简介2 蜂鸣器电路设计1 简介 蜂鸣器是一种一体化结构的电子讯响器&#xff0c;采用直流电压供电&#xff0c;广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中做发声器件。 蜂鸣器的分类&#xff1a;压电…

【ASM】字节码操作 工具类与常用类 AnalyzerAdapter初步介绍

文章目录 1.概述1.1 第一句话1.2 第二句话2. AnalyzerAdapter2.1 class info2.2 fields2.3 constructors2.4 methods2.4.1 execute方法2.4.2 return和throw2.4.3 jump2.4.4 visitFrame方法2.4.5 new和invokespecial1.概述 在上一篇文章:

创建KVM虚拟机公共镜像

手动配置kvm教程&#xff1a; https://blog.csdn.net/nvd11/article/details/127435990 但是毕竟每次创建新的虚拟机时&#xff0c;还要装一次系统比较麻烦。 打算做个公共的ubuntu镜像出来。 目标&#xff1a; NoDESCcpu数内存第一步创建虚拟机vm128g第二步创建虚拟机镜像文…

第五章《类的继承》第1节:继承的概念与实现方式

继承是面向对象最显著的一个特性,它是以已存在的类为基础定义新类的技术,新的类可以继承已有类的属性和方法,也可以增加新的类成员。 5.1.1什么是继承 在现实生活中,一类事物往往都可以划分成更小的类别。例如:“人”就是一类事物,按照人的身份和职业,可以把人划分成学…

SSTV慢速扫描的几种模式优劣对比

下面使用的图片是我自己拍摄的照片,无版权问题 原图: 扫描环境: 家中客厅,窗户打开,窗外有鸟叫和人声.模拟了介于野外和户外之间的环境 ,两部设备相隔1厘米,音量35%,所有测试下来设备未移动. Martin1 模式 : 扫描时长: 1分55秒 扫描后图片 Martin2 模式 : 扫描时长: 58秒…

Pywinauto的安装及使用

目录 1.pywinauto简单介绍 2.pywinauto的安装 3. 通过启动windows自带记事本&#xff0c;检查是否可正常使用 1.pywinauto简单介绍 pywinauto是一组用于自动化测试脚本的python模块&#xff0c;用于自动化Microsoft Windows GUI。它允许将鼠标和键盘操作发送到windows对话框…

基于JSP的企业固定资产管理系统【数据库设计、源码、开题报告】

数据库脚本下载地址&#xff1a; https://download.csdn.net/download/itrjxxs_com/86466989 主要使用技术 SpringStruts2HibernateJSPCSSJSMysql 功能介绍 固定资产管理系统是对高校固定资产的一个信息化管理系统&#xff0c;基本功能包括&#xff1a; 对固定资产的购进、…

基于遥感和GIS技术的生态承载力评价的解决方案

生态承载力的概念最早来自于生态学。1921年&#xff0c;Park和Burgess在生态学领域中首次应用了生态承载力的概念&#xff0c;即在某一特定环境条件下&#xff08;主要指生存空间、营养物质、阳光等生态因子的组合&#xff09;&#xff0c;某种个体存在数量的最高极限。生态承载…

2023-2028年中国化肥行业市场需求预测与投资趋势分析报告

本报告由锐观咨询重磅推出&#xff0c;对中国化肥行业的发展现状、竞争格局及市场供需形势进行了具体分析&#xff0c;并从行业的政策环境、经济环境、社会环境及技术环境等方面分析行业面临的机遇及挑战。还重点分析了重点企业的经营现状及发展格局&#xff0c;并对未来几年行…

m分集2跳OFDM系统中基于功率分配和子载波配对算法的信道容量matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 随着当代无线通信事业的迅猛发展,无线频谱资源已显得越来越匮乏,传统固定静态的无线频谱分配模式和策略,很难为未来的无线通信事业的进一步发展提供更多可利用的无线频谱带宽和更高的频谱…

源码分析 Laravel 重复执行同一个队列任务的原因

发现问题 在 Laravel 中使用 Redis 处理队列任务&#xff0c;框架提供的功能非常强大&#xff0c;但是最近遇到一个问题&#xff0c;就是发现一个任务被多次执行&#xff0c;这是为什么呢&#xff1f; 先说原因&#xff1a; 因为在 Laravel 中如果一个队列&#xff08;任务&a…

Java项目:JSP民宿预订网站信息管理平台

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目为前后台&#xff0c;包括管理员与普通用户两种角色&#xff1b; 管理员角色包含以下功能&#xff1a; 管理员登录,用户管理,会员管理,…

高斯消元总结

A-Matrix Equation_第 45 届国际大学生程序设计竞赛&#xff08;ICPC&#xff09;亚洲区域赛&#xff08;济南&#xff09;&#xff08;重现赛&#xff09; 自己写一个2维矩阵或者3维矩阵就可以发现对于每一列来说都是独立的&#xff0c;每一列的n个Cij都是都关系的&#xff0c…

Sentinel熔断降级

Sentinel熔断降级 1、介绍 官网地址&#xff1a;https://github.com/alibaba/Sentinel/wiki/熔断降级 Sentinel 提供以下几种熔断策略&#xff1a; 慢调用比例 (SLOW_REQUEST_RATIO)&#xff1a;选择以慢调用比例作为阈值&#xff0c;需要设置允许的慢调用 RT&#xff08;即最…

cesium for ue5中actor的cesium georeference组件的改变

今天&#xff0c;重新回顾下cesium for ue的教程&#xff0c;actor添加cesium georeference组件 发现在ue5中&#xff0c;没有这个组件了&#xff0c; 忍住卸载ue5&#xff0c;重新安装ue4.27的冲动&#xff0c;cesium的组件数量增多了&#xff0c;反而功能减少了&#xff…

hive的安装配置及使用

hive需要MySQL和hadoop的支持 文章目录hive需要MySQL和hadoop的支持安装完毕MySQL之后下载并解压hive添加系统环境变量配置hive修改 vim hive-env.sh修改hive-site.xml(1、简化配置&#xff08;推荐&#xff09;)修改hive-site.xml(2、在简化的基础上添加了部分配置)下载一个my…