当前位置: 首页 > 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;更轻松 、 更 准 确 地 设…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...