【Golang 面试基础题】每日 5 题(十)

  1.  ✍个人博客:Pandaconda-CSDN博客

📣专栏地址:http://t.csdnimg.cn/UWz06

📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~
❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

46. Go  方法值接收者和指针接收者的区别?

在 Go 中,方法可以定义在结构体类型上。接收者是指在方法定义中声明的函数参数。接收者可以是值接收者,也可以是指针接收者。值接收者在方法调用时会对接收者进行复制,而指针接收者则会使用指针来引用原始接收者。

使用值接收者时,方法中对接收者所做的任何修改都不会影响原始接收者。而使用指针接收者时,方法中对接收者所做的任何修改都将影响原始接收者。

另外,指针接收者的优势在于它可以避免在每次调用方法时复制接收者,从而提高程序的性能。此外,在某些情况下,只有使用指针接收者才能修改接收者的状态,因为值接收者只能修改接收者的副本。

例如,以下代码演示了一个使用值接收者和指针接收者的方法:

type Counter struct {count int
}// 值接收者方法
func (c Counter) increment() {c.count++
}// 指针接收者方法
func (c *Counter) decrement() {c.count--
}func main() {// 值接收者方法不会改变原始接收者的值c1 := Counter{count: 0}c1.increment()fmt.Println(c1.count) // 输出 0// 指针接收者方法会改变原始接收者的值c2 := Counter{count: 0}c2.decrement()fmt.Println(c2.count) // 输出 -1
}

在上面的示例中,increment() 方法使用值接收者,而 decrement() 方法使用指针接收者。在调用 increment() 方法后,原始 Counter 结构体实例的 count 属性保持为零,因为该方法对接收者的修改只影响了接收者的副本。而在调用 decrement() 方法后,原始 Counter 结构体实例的 count 属性减少了一,因为该方法直接修改了原始接收者。

 47. Go 函数返回局部变量的指针是否安全?

一般来说,局部变量在函数返回后被销毁,因此被返回的引用就成为了 "无所指" 的引用,程序会进入未知状态。

但这在 Go 中是安全的,Go 编译器将会对每个局部变量进行逃逸分析。如果发现局部变量的作用域超出该函数,则不会将内存分配在栈上,而是分配在堆上,因为他们不在栈区,即使释放函数,其内容也不会受影响。

package mainimport "fmt"func add(x, y int) *int {res := 0res = x + yreturn &res
}func main() {fmt.Println(add(1, 2))
}

这个例子中,函数 add 局部变量 res 发生了逃逸。res 作为返回值,在 main 函数中继续使用,因此 res 指向的内存不能够分配在栈上,随着函数结束而回收,只能分配在堆上。

编译时可以借助选项 -gcflags=-m,查看变量逃逸的情况。

./main.go:6:2: res escapes to heap:
./main.go:6:2:   flow: ~r2 = &res:
./main.go:6:2:     from &res (address-of) at ./main.go:8:9
./main.go:6:2:     from return &res (return) at ./main.go:8:2
./main.go:6:2: moved to heap: res
./main.go:12:13: ... argument does not escape
0xc0000ae008

res escapes to heap 即表示 res 逃逸到堆上了。

48. def er 的执行顺序是什么? defer的作用和特点是什么?

在 Go 语言中,defer 是一种延迟执行机制,用于在函数退出前执行一些特定的代码,无论是函数正常返回还是发生异常。defer 语句是在函数调用结束后执行的,即使出现错误或 panic 也会执行。defer 可以用于清理资源、处理错误等场景。

defer 语句的执行顺序是 “后进先出” 的,也就是说最后一个被 defer 的语句会最先执行,直到第一个被 defer 的语句执行完毕为止。

例如,下面的代码中,defer 语句的执行顺序是 3、2、1。

func example() {defer fmt.Println("1")defer fmt.Println("2")defer fmt.Println("3")fmt.Println("done")
}

需要注意的是,defer 延迟执行的代码并不是在函数退出前立即执行,而是在函数执行结束后,当函数返回时才会执行。因此,如果在 defer 语句中使用的变量在函数返回前发生了改变,那么最终执行的代码将使用最终值。

49. Go  defer 关键字的实现原理?

定义

defer 能够让我们推迟执行某些函数调用,推迟到当前函数返回前才实际执行。defer 与 panic 和 recover 结合,形成了 Go 语言风格的异常与捕获机制。

使用场景

defer 语句经常被用于处理成对的操作,如文件句柄关闭、连接关闭、释放锁。

优点:

方便开发者使用。

缺点:

有性能损耗。

实现原理

Go1.14 中编译器会将 defer 函数直接插入到函数的尾部,无需链表和栈上参数拷贝,性能大幅提升。把 defer 函数在当前函数内展开并直接调用,这种方式被称为 open coded defer。

源代码:

func A(i int) {defer A1(i, 2*i)if(i > 1) {defer A2("Hello", "eggo")}// code to do somethingreturn
}
func A1(a,b int) {//......
}
func A2(m,n string) {//......
}

编译后(伪代码):

func A(i int) {// code to do somethingif(i > 1){A2("Hello", "eggo")}A1(i, 2*i)return
}

代码示例

  1. 函数退出前,按照先进后出的顺序,执行 defer 函数

    package mainimport "fmt"// defer:延迟函数执行,先进后出
    func main() {defer fmt.Println("defer1")defer fmt.Println("defer2")defer fmt.Println("defer3")defer fmt.Println("defer4")fmt.Println("11111")
    }// 11111
    // defer4
    // defer3
    // defer2
    // defer1
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  2. panic 后的 defer 函数不会被执行(遇到 panic,如果没有捕获错误,函数会立刻终止)

    package mainimport "fmt"// panic后的defer函数不会被执行
    func main() {defer fmt.Println("panic before")panic("发生panic")defer func() {fmt.Println("panic after")}()
    }// panic before
    // panic: 发生panic
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==
  3. panic 没有被 recover 时,抛出的 panic 到当前 goroutine 最上层函数时,最上层程序直接异常终止。

    package mainimport "fmt"func F() {defer func() {fmt.Println("b")}()panic("a")
    }// 子函数抛出的panic没有recover时,上层函数时,程序直接异常终止
    func main() {defer func() {fmt.Println("c")}()F()fmt.Println("继续执行")
    }// b
    // c
    // panic: a
    wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

  4. panic 有被 recover 时,当前 goroutine 最上层函数正常执行。 

 

package mainimport "fmt"func F() {defer func() {if err := recover(); err != nil {fmt.Println("捕获异常:", err)}fmt.Println("b")}()panic("a")
}func main() {defer func() {fmt.Println("c")}()F()fmt.Println("继续执行")
}// 捕获异常: a
// b
// 继续执行
// c

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue3里将table表格中的数据导出为excel

想要实现前端对表格中的数据进行导出,这里推荐使用xlsx这个依赖库实现。 1、安装 pnpm install xlsx 2、使用 import * as XLSX from "xlsx"; 直接在组件里导入XLSX库,然后给表格table通过ref创建响应式数据拿到table实例,将实…

CSS 基础知识

CSS(级联样式表)是设置 Web 内容样式的代码。CSS 基础知识将介绍入门所需的内容。我们将回答以下问题:如何将文本设置为红色?如何使内容显示在(网页)布局中的某个位置?如何用背景图片和颜色装饰我的网页? 什么是CSS? 像HTML一样,CSS不是一种编程语言。它也不是一种标…

拉提查合创5步玩转git工具协作代码开发

1 工具使用场景 开发团队使用git版本管理工具,进行协作代码开发过程中,最常用的场景为: (1)拉取代码 将git远端仓库最新代码拉取到本地。 (2)提交代码 将本地新增修改的代码提交至git远端仓库中…

【Django】开源前端库bootstrap,常用

文章目录 下载bootstrap源文件到本地项目引入bootstrap文件 官网:https://www.bootcss.com/V4版本入口:https://v4.bootcss.com/V5版本入口:https://v5.bootcss.com/ 这里使用成熟的V4版本,中文文档地址:https://v4.b…

SpringBoot整合SSE技术详解

Hi 👋, Im shy SpringBoot整合SSE技术详解 1. 引言 在现代Web应用中,实时通信变得越来越重要。Server-Sent Events (SSE)是一种允许服务器向客户端推送数据的技术,为实现实时更新提供了一种简单而有效的方法。本文将详细介绍如何在SpringBoot中整合SSE,并探讨S…

Java的四种引用类型

Java的四种引用类型 1. 强引用(Strong Reference)2. 软引用(Soft Reference)3. 弱引用(Weak Reference)4. 虚引用(Phantom Reference) 💖The Begin💖点点关注…

go-kratos 学习笔记(4) 服务注册与发现 nacos注册

接口实现​ Registry 接口分为两个,Registrar 为实例注册和反注册,Discovery 为服务实例列表获取 type Registrar interface {// 注册实例Register(ctx context.Context, service *ServiceInstance) error// 反注册实例Deregister(ctx context.Context…

大模型算法面试题(十二)

本系列收纳各种大模型面试题及答案。 1、领域模型Continue PreTrain数据如何选取 在领域模型的Continue PreTrain(持续预训练)过程中,数据选取是一个至关重要的步骤,它直接影响模型在特定领域上的性能和泛化能力。以下是一些关于…

【机器学习】深入理解损失函数(Loss Functions)

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 深入理解损失函数(Loss Functions)什么是损失函数?常见损失函数类型1. 均方误差…

OSPF概述

OSPF OSPF属于内部网关路由协议【IGP】 用于单一自治系统【Autonomous System-AS】内决策路由 自治系统【AS】 执行统一路由策略的一组网络设备的组合 OSPF概述 为了适应大型的网络,OSPF在AS内划分多个区域 每个OSPF路由器只维护所在区域的完整的链路状态信息 …

谷粒商城实战笔记-62-商品服务-API-品牌管理-OSS整合测试

文章目录 一,Java中上传文件到阿里云OSS1,整合阿里云OSS2,测试上传文件 二,Java中整合阿里云OSS服务指南引言准备工作1. 注册阿里云账号2. 获取Access Key3. 添加依赖 实现OSS客户端1. 初始化OSSClient2. 创建Bucket3. 上传文件4.…

ElasticSearch(七)— 相关性检索和组合查询

一、 相关性评分 全文检索与数据库查询的一个显著区别, 就是它并不一定会根据查询条件 做完全精确的匹配。除了模糊查询以外,全文检索还会根据查询条件给文档的相关性打分并排序,将那些与查询条件相关性高的文档排在最前面。 相关性( Relev…

Cocos Creator2D游戏开发-(1)初始化设置

初心: 做一款微信或者抖音小游戏,然后发布,对于我来说这是一个新的赛道; 写这些文档的原因,记录一下自己学习过程,下次用的时候方便找 cocos creator版本: 3.8.3 当前小游戏飞机大战教程来源于: 抖音: 禅影 chanying001 源码目录: https://www.kdocs.cn/l/caLr6XCbEfPa 创建一个…

【CN】Argo 持续集成和交付(一)

1.简介 Argo 英 [ˈɑ:ɡəu] 美 [ˈɑrˌɡo] Kubernetes 原生工具,用于运行工作流程、管理集群以及正确执行 GitOps。 Argo 于 2020 年 3 月 26 日被 CNCF 接受为孵化成熟度级别,然后于 2022 年 12 月 6 日转移到毕业成熟度级别。 argoproj.github.i…

关键词查找【Knuth-Morris-Pratt (KMP) 算法】

一个视频让你彻底学懂KMP算法_哔哩哔哩_bilibili KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。 第一步:计算模式串(子串)和next[j]数组 模式串 前2位字母的next[j]固定是0 和 1 后续字母的nex[j]&…

MySql-函数

一、什么是函数? 数学函数 用作常规的数学运算; 字符串函数 对于字符串类型的字段处理; 日期时间函数 对于日期和时间类型的字段进行 处理; 聚合函数 常用于GROUP BY从句的 SELECT查询中; 自定义函数 根据实际需求…

Telegram曝零日漏洞,可伪装成视频攻击安卓用户

ESET Research在一个地下论坛上发现了一个针对Android Telegram的零日漏洞广告。 ESET将该漏洞命名为“EvilVideo”,并将其报告给Telegram,Telegram于7月11日更新了该应用程序。 EvilVideo允许攻击者发送恶意的有效载荷,这些载荷以视频文件…

Redis - SpringDataRedis - RedisTemplate

目录 概述 创建项目 引入依赖 配置文件 测试代码 测试结果 数据序列化器 自定义RedisTemplate的序列化方式 测试报错 添加依赖后测试 存入一个 String 类型的数据 测试存入一个对象 优化 -- 手动序列化 测试存入一个Hash 总结: 概述 SpringData 是 S…

PSINS工具箱函数介绍——insplot

insplot是一个绘图命令,用于将avp数据绘制出来 本文所述的代码需要基于PSINS工具箱,工具箱的讲解: PSINS初学指导使用方法 此函数使用起来也很简单,直接后面加avp即可,如: insplot(avp);其中,avp为: 每行表示一个时间1~3列为三轴姿态角(a),4-6列为三位速度(v),…

Milvus 向量数据库进阶系列丨部署形态选型

本系列文章介绍 在和社区小伙伴们交流的过程中,我们发现大家最关心的问题从来不是某个具体的功能如何使用,而是面对一个具体的实战场景时,如何选择合适的向量数据库解决方案或最优的功能组合。在 “Milvus 向量数据库进阶” 这个系列文章中&…