当前位置: 首页 > news >正文

你会处理 go 中的 nil 吗

对于下面这段代码,我们知道 i 实际上的值就是 nil,所以 i == nil 会生效

func main() {var i *int = nilif i == nil {fmt.Println("i is nil") // i is nil}
}

现在换一种写法,我们将 i 的类型改成 interface{},i == nil 依然会生效

func main() {var i interface{} = nilif i == nil {fmt.Println("i is nil") // i is nil}
}

我们接着改造,将

 i == nil 的逻辑封装成函数 IsNil
go复制代码func IsNil(i interface{}) {if i == nil {fmt.Println("i is nil")}
}
func main() {var i *int = nilIsNil(i)
}

居然发现 IsNil 中的 i == nil 不生效了
这是为什么呢?
因为对于 interface{} 类型的值来说,如果要判断它是 nil,必须同时满足 type T 和 value V 都是 nil 才行
可以用 reflect 中的 TypeOf 和 ValueOf

var i *int = nil
fmt.Println(reflect.TypeOf(i), reflect.ValueOf(i)) // *int  <nil>var i interface{} = nil
fmt.Println(reflect.TypeOf(i), reflect.ValueOf(i)) // <nil> <invalid reflect.Value>

如果我们在函数中用 interface{} 作为参数的类型,表示并不代表参数就是 interface{} 类型,而是任意类型,调用时传入啥类型就是啥类型,如下代码

var i interface{} = 1
fmt.Println(reflect.TypeOf(i)) // intvar j interface{} = "hello"
fmt.Println(reflect.TypeOf(j)) // stringvar k interface{} = nil
fmt.Println(reflect.TypeOf(k)) // nil

所以只有当我们传入的参数类型是 interface{},且 value 为 nil 时,i == nil 才会生效
否则其他情况都不会生效

func main() {var i interface{} = nilIsNil(i)  // i is nil
}
func IsNil(i interface{}) {if i == nil {fmt.Println("i is nil")}
}

这个坑可能会出现在返回 error 的函数中,比如下面这段代码
在函数 SomeThing 中提前定义了 myError,然后一系列的处理后,返回了 myError
后面的业务逻辑需要判断 err 是否为 nil

type MyError struct{}
func (me *MyError) Error() string {return "my error"
}
func SomeThing() error {var myError *MyError    // 默认初始化为 nil// ...return myError
}
func main() {err := SomeThing()fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err)) // *main.MyError <nil>if err != nil {     // 虽然没有返回,这里会被执行,因为 err 的类型不是 nilfmt.Println(err)}
}

从上面的代码我们看到,SomeThing 函数中定义的 myError 是 *MyError 类型,虽然返回了 nil,但是 err 的类型不是 nil,所以 err != nil 会生效,不符合预期
如果修改这个问题呢,当我们需要返回 nil 时,显示指明返回 nil,如下代码:

type MyError struct{}
func (me *MyError) Error() string {return "my error"
}
func SomeThing() error {var myError *MyError    // 默认初始化为 nil// ...return nil
}
func main() {err := SomeThing()fmt.Println(reflect.TypeOf(err), reflect.ValueOf(err)) // <nil> <invalid reflect.Value>if err != nil {     // 这段代码不会被执行fmt.Println(err)}
}

总结:需要返回 nil 时,要显示返回 nil,不要用指针类型的零值

相关文章:

你会处理 go 中的 nil 吗

对于下面这段代码&#xff0c;我们知道 i 实际上的值就是 nil&#xff0c;所以 i nil 会生效 func main() {var i *int nilif i nil {fmt.Println("i is nil") // i is nil} }现在换一种写法&#xff0c;我们将 i 的类型改成 interface{}&#xff0c;i nil 依然…...

高级深入--day42

注意&#xff1a;模拟登陆时&#xff0c;必须保证settings.py里的 COOKIES_ENABLED (Cookies中间件) 处于开启状态 COOKIES_ENABLED True 或 # COOKIES_ENABLED False 策略一&#xff1a;直接POST数据&#xff08;比如需要登陆的账户信息) 只要是需要提供post数据的&#xff…...

mysql 计算两个坐标距离

方式一&#xff1a;st_distance_sphere 计算结果单位米 SELECT *, st_distance_sphere(point(lng,lat),point(lng,lat)) as distance FROM table mysql 版本5.7 以上 方式二&#xff1a;st_distance 计算结果单位是度 SELECT *, (st_distance(point(lng,lat),point(lng4,lat…...

String、StringBuffer、StringBuilder和StringJoiner

String、StringBuffer、StringBuilder和StringJoiner都是用于处理字符串的类&#xff0c;但它们在性能和使用方式上有一些区别。 String String是不可变的类&#xff0c;一旦创建就不能被修改。对String进行拼接或修改时&#xff0c;实际上是创建了一个新的String对象。适用于…...

【数据结构】插入排序

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈数据结构 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 直接插入、希尔排序 1. 什么是排序2…...

Photoshop使用笔记总目录

Photoshop基础学习之工具学习 一、【Photoshop界面认识】 二、【 Photoshop常用快捷键】 三、【色彩模式与颜色填充】 四、【选区】 五、【视图】 六、【常用工具组】 七、【套索工具组】 八、【快速选择工具组】 九、【裁剪工具组】 十、【图框工具组】 十一、【吸取…...

最近面试遇到的高频面试题

大家好&#xff0c;我是 jonssonyan 互联网寒冬&#xff1f;金九银十真的不存在了么&#xff1f;虽说现在行情是差了一些&#xff0c;面试机会少了一些&#xff0c;但是大部分公司还是或多或少的招人&#xff0c;春招秋招都在进行。有人离职就有人入职。所以如果你还没约到面试…...

负载均衡有哪些算法,分别在nginx中如何配置?

负载均衡是用于分发传入的网络流量到多个后端服务器的技术&#xff0c;以确保无单个服务器过载&#xff0c;从而提高应用的可用性和响应时间。以下是一些常用的负载均衡算法&#xff0c;以及如何在Nginx中配置它们&#xff1a; 轮询 (Round Robin)&#xff1a; 简介&#xff1a…...

Starknet开发工具

1. 引言 目前Starknet的开发工具流可为&#xff1a; 1&#xff09;Starkli&#xff1a;音为Stark-lie&#xff0c;为替换官方starknet-CLI的快速命令行接口。Starkli为单独的接口&#xff0c;可独自应用&#xff0c;而不是其它工具的组件。若只是想与Starknet交互&#xff0…...

Unity地面交互效果——1、局部UV采样和混合轨迹

大家好&#xff0c;我是阿赵。   这期开始&#xff0c;打算介绍一下地面交互的一些做法。 比如&#xff1a; Unity引擎制作沙地实时凹陷网格的脚印效果 或者&#xff1a; Unity引擎制作雪地效果 这些效果的实现&#xff0c;需要基于一些基础的知识。所以这一篇先介绍一下简单…...

基于STM32的示波器信号发生器设计

**单片机设计介绍&#xff0c;基于STM32的示波器信号发生器设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序文档 六、 文章目录 一 概要 基于STM32的示波器信号发生器是一种高性能的电子仪器&#xff0c;用于测试和分析电路中的电信号。在该系统中&a…...

案例分析大汇总

案例分析心得 2018-2022年的案例分析考试内容汇总&#xff08;近五年&#xff09; 架构设计题型 软件系统建模 数据库 Web 系统设计 2018年 胖/瘦客户端 C/S 架构非功能性需求 数据流图DFDE-R图Essential Use Cases(抽象用例)&#xff0c;Real Use Cases(基础用例)信息工…...

MVCC(Multi-Version Concurrency Control,多版本并发控制)

是一种数据库管理系统中常用的并发控制技术&#xff0c;用于处理多个事务同时访问数据库数据时的数据一致性和隔离性。MVCC的主要目标是允许多个事务并发执行&#xff0c;同时保持数据的一致性&#xff0c;避免数据丢失或不一致。 MVCC 的核心思想是为每个事务维护多个版本的数…...

嵌入式面试2(c相关)

目录 1.C语言中static、const、volatile关键字用法区别&#xff1b; static的用法&#xff08;定义和用途) const的用法&#xff08;定义和用途&#xff09; volatile (英文意思为易变的) 作用和用法&#xff1a; 2.C语言中&#xff0c;const 和 static 的区别&#xff0c;c…...

基于SSM的n省出口基地公共信息服务平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

opencv dnn模块 示例(20) 目标检测 object_detection 之 yolor

文章目录 1、论文介绍1.1、YOLOR思想动机1.2、隐式知识学习1.2.1、隐式知识如何工作1.2.2、隐式知识统一网络建模 1.3、实验1.4、总结 2、测试2.1、opencv dnn2.1.1、代码2.1.2、结果 2.2、测试效率 YOLOR出自论文You Only Learn One Representation: Unified Network for Mult…...

【队列的顺序表示,链式表示】

文章目录 队列的表示和实现相关术语队列的表示链队的表示链队的定义链队的初始化销毁链队列 链队列的入队出栈 队列的表示和实现 相关术语 队列&#xff08;Queue&#xff09;是仅在表尾进行插入操作&#xff0c;在表头进行删除操作的线性表。表尾即an端&#xff0c;称为队尾…...

Pydantic 实践

1. 简介 pydantic 库是一种常用的用于数据接口 schema 定义与检查的库。 通过 pydantic 库&#xff0c;我们可以更为规范地定义和使用数据接口&#xff0c;这对于大型项目的开发将会更为友好。 当然&#xff0c;除了 pydantic 库之外&#xff0c;像是 valideer 库、marshmallo…...

获取pandas中的众数

pandas.DataFrame 也有一个 mode() 方法。 以下面的 pandas.DataFrame 为例。 df pd.DataFrame({‘col1’: [‘X’, ‘X’, ‘Y’, ‘X’], ‘col2’: [‘X’, ‘Y’, ‘Y’, ‘X’]}, index[‘row1’, ‘row2’, ‘row3’, ‘row4’]) print(df) col1 col2 row1 X X row2…...

SOLIDWORKS Simulation2024仿真10大新功能

SOLIDWORKS Simulation新增功能 1. 增强型轴承接头 •通过指定压缩、拉伸和弯曲的刚度&#xff0c;轻松创建自定义轴承接头。•通过向非线性和大型位移算例添加自定义条件&#xff0c;提高模拟精度。 优点&#xff1a;使用功能强大的接口&#xff0c;更轻松 、 更 准 确 地 设…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...