你会处理 go 中的 nil 吗

news/2024/7/24 7:11:47 标签: golang, 开发语言, 后端

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

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

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

func main() {
  var i interface{} = nil
  if 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 = nil
  IsNil(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)) // int

var j interface{} = "hello"
fmt.Println(reflect.TypeOf(j)) // string

var k interface{} = nil
fmt.Println(reflect.TypeOf(k)) // nil

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

func main() {
  var i interface{} = nil
  IsNil(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 的类型不是 nil
    fmt.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,不要用指针类型的零值


http://www.niftyadmin.cn/n/5134135.html

相关文章

TIDB日期和时间类型

TIDB日期和时间类型 一、日期和时间 DATE、DATETIME和TIMESTAMP 1、DATE DATE 类型的格式为 YYYY-MM-DD&#xff0c;支持的范围是 1000-01-01 到 9999-12-31。 2、TIME 类型 TIME 类型的格式为 HH:MM:SS[.fraction]&#xff0c;支持的范围是 -838:59:59.000000 到 838:59…

H5游戏源码分享-像素小鸟游戏(类似深海潜艇)

H5游戏源码分享-像素小鸟游戏&#xff08;类似深海潜艇&#xff09; 点击屏幕控制小鸟的飞行高度 整个小游戏就用JS完成 项目地址&#xff1a;https://download.csdn.net/download/Highning0007/88483228 <!DOCTYPE HTML> <html><head><meta http-equiv…

数据结构-顺序表6

八.返回key的前驱下标&#xff0c;如果不存在&#xff08;key无前驱&#xff0c;在表头&#xff09;返回-1函数 思路&#xff1a;找到key的前驱&#xff0c;调用Search函数找key就可以 这里把i<0写成i<0&#xff0c;也是可以的&#xff0c;因为i0接着进入下面return i-1…

android中gradle的kotlin编译配置选项

一、编译配置 1、Android中的配置 使用如下方式开启在Android中的gradle的kotlin编译配置&#xff1a; 该配置在其余平台不可用 android {...compileOptions {sourceCompatibility JavaVersion.VERSION_17targetCompatibility JavaVersion.VERSION_17}kotlinOptions {jvmTar…

GEE错误——影像加载过程中出现的图层无法展示的解决方案

问题&#xff1a; // I dont know if some standard value exists for the radius, in the same, I will assume that some software would prefer to use square shape, but circle makes more sense to me. // pixels is noice if you want to zoom in and out to visualize…

Python beautifulsoup解析本地文件之基础语法

视频版教程&#xff1a;一天掌握python爬虫【基础篇】 涵盖 requests、beautifulsoup、selenium beautifulsoup支持解析本地文件和网络文件&#xff0c;需要注意的是在实例化 BeautifulSoup 对象时&#xff0c;“html.parser” 是一个解析器&#xff0c;用于解析 HTML 代码&am…

css position属性与js滚动

“视口”就是浏览器窗口中实际显示文档内容的区域&#xff0c;不包含浏览器的“外框”&#xff0c;如菜单、工具条和标签。文档则是指整个网页。 1 css 的position static 正常定位&#xff0c;是元素position属性的默认值&#xff0c;元素遵循常规流。 relative 相对定位&…

lv8 嵌入式开发 网络编程开发 21 私有云盘项目

目录 1云盘项目简介 2 项目实现 2.1 首先实现TCP客户端、服务端 2.2 实现客户端函数简化 2.3 实现服务端函数简化 2.4 TCP数据连包现象 2.5 封装send函数和recv函数 2.6 建立readme说明 2.7 实现文件传输 2.8 读取配置文件种的ip、端口号,通过argv[1]参数实现文件传输…