【Golang 面试 - 基础题】每日 5 题(九)
✍个人博客:Pandaconda-CSDN博客
📣专栏地址:http://t.csdnimg.cn/UWz06📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪
41. Go channel 有什么特点?
channel 有 2 种类型:无缓冲、有缓冲
channe l有 3 种模式:写操作模式(单向通道)、读操作模式(单向通道)、读写操作模式(双向通道)
| 写操作模式 | 读操作模式 | 读写操作模式 | |
| 创建 | make(chan<- int) | make(<-chan int) | make(chan int) |
channel 有 3 种状态:未初始化、正常、关闭
| 未初始化 | 关闭 | 正常 | |
| 关闭 | panic | panic | 正常关闭 |
| 发送 | 永远阻塞导致死锁 | panic | 阻塞或者成功发送 |
| 接收 | 永远阻塞导致死锁 | 缓冲区为空则为零值,否则可以继续读 | 阻塞或者成功接收 |
注意点:
-
一个 channel 不能多次关闭,会导致 painc。
-
如果多个 goroutine 都监听同一个 channel,那么 channel 上的数据都可能随机被某一个 goroutine 取走进行消费。
-
如果多个 goroutine 监听同一个 channel,如果这个 channel 被关闭,则所有 goroutine 都能收到退出信号。
42. Go 语言当中 Channel(通道)有什么特点,需要注意什么?
在 Go 语言中,Channel 是一种用于 Goroutine 之间通信和同步的重要机制。Channel 具有以下几个特点:
-
线程安全:Channel 可以安全地在多个 Goroutine 之间传递数据,避免了数据竞争和死锁等问题。
-
阻塞式:当 Channel 中没有数据时,读取操作会被阻塞,直到 Channel 中有数据可读;同样地,当 Channel 已满时,写入操作会被阻塞,直到 Channel 中有空间可写入。
-
有缓冲和无缓冲:Channel 可以带有缓冲或者不带缓冲。不带缓冲的 Channel 可以保证每次写入和读取都是同步的;带缓冲的 Channel 可以在缓冲区未满时进行写入操作而不阻塞,直到缓冲区满时再阻塞写入操作。
-
可关闭:Channel 可以被显式地关闭,以通知 Channel 的接收方不再有数据可读,避免接收方被永久地阻塞。
在使用 Channel 时,需要注意以下几个问题:
-
避免死锁:当使用 Channel 进行 Goroutine 之间的通信和同步时,需要确保不会出现死锁的情况。一般来说,可以使用 select 语句和超时机制等方式来避免 Channel 的阻塞问题。
-
避免竞态条件:当多个 Goroutine 访问同一个 Channel 时,需要注意避免竞态条件的发生。可以使用 Mutex 和 sync 包中提供的其他同步机制来避免并发访问 Channel 导致的问题。
-
合理使用缓冲:当使用带缓冲的 Channel 时,需要根据实际需要设置缓冲区的大小,避免缓冲区过大或过小导致的性能问题。同时需要注意,当 Channel 中的数据过多时,会导致内存占用过高,需要及时清理不必要的数据。
-
避免 Channel 泄漏:当使用 Channel 时,需要注意避免 Channel 泄漏的问题,即在不需要使用 Channel 时及时关闭 Channel,避免 Channel 占用过多的系统资源。
实例
以下是一个使用同步锁和 Channel 进行并发编程的例子:
package mainimport ("fmt""sync"
)func main() {var wg sync.WaitGroupwg.Add(2)ch := make(chan int, 5)mutex := sync.Mutex{}go func() {defer wg.Done()for i := 0; i < 10; i++ {mutex.Lock()ch <- imutex.Unlock()}}()go func() {defer wg.Done()for i := 0; i < 10; i++ {mutex.Lock()fmt.Println(<-ch)mutex.Unlock()}}()wg.Wait()close(ch)
}
上述代码中,我们创建了一个有缓冲的 Channel,使用一个 Goroutine 向其中写入数据,另一个 Goroutine 从中读取数据,并使用同步锁保证对 Channel 的访问是线程安全的。在主函数中,我们使用 sync.WaitGroup 来等待两个 Goroutine 完成任务,并在任务完成后关闭 Channel。
43. Go 语言当中 Channel 缓冲有什么特点?
在 Go 语言中,Channel 缓冲是指在创建 Channel 时设置的缓冲区大小。带缓冲的 Channel 可以在缓冲区未满时进行写入操作而不阻塞,直到缓冲区满时再阻塞写入操作。
Channel 缓冲的特点如下:
-
可以提高并发性能:使用带缓冲的 Channel 可以提高并发程序的性能,因为缓冲区可以暂时存储数据,避免了每次数据传输时都需要阻塞等待的情况。这种方式特别适用于生产者-消费者模式,其中生产者的产生速度快于消费者的处理速度,缓冲区可以暂时存储一定量的数据,使得生产者和消费者的速度可以适度地解耦。
-
缓冲区大小需要合理设置:Channel 缓冲区大小的设置需要根据实际应用场景进行合理的选择,过小的缓冲区可能会导致生产者被阻塞,过大的缓冲区可能会导致内存占用过高。一般来说,需要根据实际情况进行调整,以达到最优的性能表现。
-
带缓冲的 Channel 可能会出现死锁问题:当使用带缓冲的 Channel 进行 Goroutine 之间的通信和同步时,需要注意避免死锁的问题。因为带缓冲的 Channel 可以在缓冲区未满时进行写入操作,如果生产者写入数据的速度过快,可能会导致缓冲区已满而阻塞生产者,此时如果消费者已经不再消费数据,整个程序就会进入死锁状态。
-
可以使用 close() 函数关闭 Channel:当使用带缓冲的 Channel 时,需要注意及时清理缓冲区中的数据,可以使用 close() 函数来显式地关闭 Channel。关闭 Channel 会使得 Channel 中未被读取的数据被丢弃,并且后续的写入操作会导致 panic 异常。
实例
举个例子,假设有一个生产者-消费者模式的场景,生产者不断地向 Channel 中写入数据,而消费者则以固定的速度从 Channel 中读取数据进行处理。如果使用带缓冲的 Channel,可以设置缓冲区大小为一定的值,比如 10,这样生产者可以连续向 Channel 中写入 10 个数据,只有当 Channel 中已经存储了 10 个数据时才会阻塞。而消费者则可以按照自己的处理速度从 Channel 中读取数据,只有当 Channel 中的数据被消费完时才会阻塞等待新的数据。这样可以提高程序的并发性能,避免频繁地阻塞等待。
package mainimport ("fmt""time"
)func producer(ch chan<- int) {for i := 1; i <= 10; i++ {ch <- ifmt.Printf("Producer: %d\n", i)}close(ch)
}func consumer(ch <-chan int) {for {data, ok := <-chif !ok {break}fmt.Printf("Consumer: %d\n", data)time.Sleep(time.Second)}
}func main() {ch := make(chan int, 5)go producer(ch)consumer(ch)
}
44. C hannel 的 ring buffer 实现
在 Go 语言中,channel 是一种用于在 goroutine 之间进行通信的机制。通常情况下,channel 会被实现为一个 FIFO 的队列。当向 channel 发送数据时,数据会被添加到队列的末尾;当从 channel 接收数据时,数据会被从队列的头部取出。
在 Go 1.3 版本中,新增了一种基于环形缓冲区(ring buffer)的 channel 实现方式,可以用于提高 channel 的性能。具体来说,当创建一个缓冲区大小为 n 的 channel 时,Go 语言会为其分配一个大小为 n 的环形缓冲区,而不是一个简单的队列。
使用环形缓冲区实现 channel 有以下几个好处:
-
避免动态内存分配:在缓冲区大小确定的情况下,环形缓冲区可以在创建时一次性分配所需的内存,避免了频繁的动态内存分配和释放操作,从而提高了性能。
-
提高缓存命中率:环形缓冲区会将元素放置在连续的内存块中,这样可以提高缓存命中率,从而减少缓存访问延迟,提高了通信的效率。
-
支持无锁访问:由于 channel 是在多个 goroutine 之间进行通信的,因此通常会涉及到并发访问的问题。环形缓冲区的实现可以采用无锁算法,从而避免了锁竞争带来的开销,提高了并发访问的效率。
需要注意的是,使用环形缓冲区实现 channel 也有一些限制和注意事项。例如,缓冲区大小必须是 2 的幂次方,否则可能会导致缓冲区溢出或者浪费内存等问题。同时,对于特殊的 channel 操作,如 close、select 和带缓冲区的 channel 等,也需要注意环形缓冲区的使用方式。
45. Go 方法与函数的区别?
在 Go 语言中,方法(method)是一个包含接收者参数的函数,用于为接收者类型提供一些行为。而函数(function)则是一段代码,可被调用并可接收参数和返回值。
方法需要被绑定到一个类型上,它们通过使用接收者参数来实现这一点。接收者可以是值类型或指针类型。值类型的接收者在方法执行时会将调用者的值复制一份,而指针类型的接收者则直接操作调用者的值,因此可以修改调用者的状态。
与方法不同,函数没有接收者参数,因此它们无法直接修改调用者的状态。函数在 Go 语言中是一等公民,可以像任何其他类型的值一样被传递和赋值。函数还可以是匿名的,或者被作为闭包使用,以便在不同的作用域中进行操作。
实例
在 Go 语言中,函数是一段代码块,可以独立调用,接受参数和返回结果,它没有任何属于对象的概念。而方法是和对象相关联的函数,它属于对象的一部分,可以调用对象的属性和方法。
例如,下面是一个函数和一个方法的示例:
// 函数
func add(x int, y int) int {return x + y
}// 方法
type Person struct {Name stringAge int
}func (p *Person) sayHello() {fmt.Printf("Hello, my name is %s and I'm %d years old.\n", p.Name, p.Age)
}
可以看到,函数 add 只是一个独立的代码块,而方法 sayHello 则是一个属于 Person 结构体对象的一部分。在调用方法时,需要先创建一个 Person 对象,然后通过这个对象调用方法,例如:
p := Person{Name: "Alice", Age: 30}
p.sayHello() // 输出:Hello, my name is Alice and I'm 30 years old.
总的来说,Go 语言中的方法与函数的区别在于方法需要绑定到一个类型上,并且可以直接修改调用者的状态,而函数则没有这些限制。
相关文章:
【Golang 面试 - 基础题】每日 5 题(九)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/UWz06 📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏…...
《程序猿入职必会(4) · Vue 完成 CURD 案例 》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
编程技巧:如何优雅地合并两个有序数组?
目录 题目引用描述1.直接合并 排序2.指针3.后逆向双指针进阶:你可以设计实现一个时间复杂度为 O(m n) 的算法解决此问题吗?总结 题目 来自力扣 引用 合并两个有序数组 给你两个按 **非递减顺序 **排列的整数数组 nums1 和 nums2,另有两个整…...
Vue组件库移动端预览实现原理
引言 大家如果使用过移动端组件库(比如:Vant),会发现在网站右侧有一个手机端的预览效果。 而且这个手机端预览的内容和外面的组件代码演示是同步的,切换组件的时候,移动端预览的内容也会发生相应的变化。 …...
FastAPI(七十五)实战开发《在线课程学习系统》接口开发-- 创建课程
源码见:"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 上次我们分享了,FastAPI(七十四)实战开发《在线课程学习系统》接口开发-- 删除留言 从本篇文章开始,…...
【C++】 条件变量实现线程同步示例
在做一些比较大的项目的时候,需要实现线程同步, 这里结合一个小示例,进行线程同步的讲解 问题定义 以下是一个使用 C 多线程和条件变量的示例,展示了线程 A 接收一个 enable 信号并通知线程 B 开始工作。线程 B 在开始工作之前…...
linux下载redis安装并指定配置文件启动
linux下载redis并安装启动: cd /usr/local/src 下载redis压缩包 wget http://download.redis.io/releases/redis-6.2.6.tar.gz 解压 tar -xzf redis-6.2.6.tar.gz 编译和安装redis make make install 安装完成后进入 redis 安装目录 cd /usr/local/bin 修改…...
线性结构、线性表、顺序表、链表、头插法、尾插法、中间插入或删除一个节点
梳理几个名词: 逻辑地址:就是说是第几个元素。 物理地址:也就是存储地址,在计算机里具体存放的位置。 线性表的存储结构分为: (1)顺序存储结构:将数据依次存储在连续的整块物理空…...
C# Task.WaitAll 的用法
目录 简介 1.WaitAll(Task[], Int32, CancellationToken) 2.WaitAll(Task[]) 3.WaitAll(Task[], Int32) 4.WaitAll(Task[], CancellationToken) 5.WaitAll(Task[], TimeSpan) 结束 简介 Task.WaitAll 是 C# 中用于并行编程的一个的方法,它属于 System.Threa…...
vue2 前端实现pdf在线预览(无插件版)
toFielDetail()是点击预览的方法,getOfficialFile是获取文件流的接口正常定义即可: export function getOfficialFile(query) {return request({url: /dataAsset/projectassess/getOfficialFile,method: get,params: query,}); } 调用接口的页面需要引用…...
排序XXXXXXXXX
信息学奥赛|常见排序算法总结(C+) - 腾讯云开发者社区-腾讯云 (tencent.com) https://cloud.tencent.com/developer/news/975232 常用序号层级排序 一、序号 序号Sequence Number,有顺序的号码,如数字序号…...
【文件解析漏洞】实战详解!
漏洞描述: 文件解析漏洞是由于中间件错误的将任意格式的文件解析成网页可执行文件,配合文件上传漏洞进行GetShell的漏洞! IIS解析漏洞: IIS6.X: 方式一:目录解析 在网站下建立文件夹的名字为.asp/.asa 的文件夹,其目…...
【杂谈】学会让你节省三秒钟——Dev-c++的缺省源
【杂谈】学会让你节省三秒钟——Dev-c的缺省源 1.前言2.缺省源的介绍3.注意 1.前言 你是否在为每次写程序都要自己手打一遍框架而感到苦恼?为什么大佬的Dev-C一新建文件就会自动出现程序框架?看完这篇文章,让你也能成为大佬,不用再…...
推荐一款前端滑动验证码插件(Vue、uniapp)
uniapp版本:滑块拼图验证码,有后端,简单几步即可实现,小程序、h5都可以用 - DCloud 插件市场 Vue版本及cdn版本可以查阅文档: 行为验证 | Poster 文档 示例代码: <template><view id"app&…...
【Git】git stash
目录 基本概念参数详解listshowsavepushpop|applydropclearbranch 参考文章 Git的stash命令是一个非常实用的功能,它允许开发者临时保存工作目录和暂存区的更改,以便能够切换到其他分支或进行其他操作,而不会丢失当前的修改。以下是git stash…...
不得不安利的程序员开发神器,太赞了!!
作为一名程序员,你是否常常为繁琐的后端服务而感到头疼?是否希望有一种工具可以帮你简化开发流程,让你专注于创意和功能开发?今天,我要向大家隆重推荐一款绝佳的开发神器——MemFire Cloud。它专为懒人开发者准备&…...
吴恩达机器学习C1W2Lab06-使用Scikit-Learn进行线性回归
前言 有一个开源的、商业上可用的机器学习工具包,叫做scikit-learn。这个工具包包含了你将在本课程中使用的许多算法的实现。 目标 在本实验室你可以: 利用scikit-learn实现基于正态方程的近似解线性回归 工具 您将使用scikit-learn中的函数以及ma…...
CSS实现表格无限轮播
<div className{styles.tableTh}><div className{styles.thItem} style{{ width: 40% }}>报警名称</div><div className{styles.thItem} style{{ width: 35% }}>开始时间</div><div className{styles.thItem} style{{ width: 25% }}>状态&…...
编程小白如何从迷茫走出
针对新生们常常感到的迷茫,以下是如何选择适合自己的编程语言、如何制定有效的学习计划以及如何避免常见的学习陷阱的详细建议: 一、如何选择适合自己的编程语言 明确需求和目标:不同的编程语言有不同的特点和适用场景。例如,Py…...
14 B端产品的运营管理
通过运营找到需求并通过交换价值提供供给,再逐步扩大规模、站稳脚跟,辅助产品在商业竞争中获胜。 B端产品运营框架 1. 打通渠道 目的:触达客户。 环节:文案策划、活动策划→广告渠道推广→线下BD。 线下BD:通过见面…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
