一、引出话题: 在开始这个话题之前,我们先看一段代码以及其输出结果,代码如下所示: 从上面的输出结果来看,GetA()返回的类型为*A就算赋值为nil,也不等于nil。...看到这里笔者觉得很奇怪,明明是GetA()返回值是nil,为什么nil的判断条件是false呢?...二、原因分析: 在研究了interface之后,笔者发现了真相,原来Go语言中的interface是不是nil的条件,不单单是interface中的值是nil,类型还需要是nil才行。...,只要有中一个不为nil,那么interface就不是nil。...验证代码如下所示: 通过上面代码的输出,我们能够看到GetA()返回的空接口,type已经被赋值了,就算value还是nil,接口a依然不会是nil。
才对,但实际上,输出的却是: err updating: 寻找原因 为什么明明返回的是 nil,却被判定为 err ≠ nil 呢?...> 所以在做 err ≠ nil 的比较时,err 的类型 T 已经不是 nil,前面已经说过,只有当一个接口变量的 T 和 V 同时为 nil 时,这个变量才会被判定为 nil,所以该不等式会判定为...,且值为 nil,所以做 err ≠ nil 的比较时结果就是将是 false。...把一个具体类型变量与 nil 比较时,只需要判断其 value 是否为 nil 即可,而把一个接口类型的变量与 nil 进行比较时,还需要判断其类型 itab._type 是否为nil。..._type 与 data 都为 nil 时,也就是实际类型和值都未被赋值前,才真正等于 nil 。
NULL = (void *)0 C指针的字面空值 nil = (id)0 OC对象的字面空值 Nil = (Class)0 OC类的字面空值...// 表示指向OC对象的指针为空 NSString *str = nil; NSURL *url = nil; id obj = nil; if (obj == nil) { // todo .....Nil // 表示只想OC类 类型的指针为空 Class class = Nil; Class class2 = [NSString class]; // 4....通常被用于表示集合对象结束的标志,\ 因此无法用nil来存储一个空值,所以一般用[NSNull null]来存 // 例1:当 NSArray 里遇到 nil 时,就说明这个数组对象的元素截止了...#warning NSArray 只关注 nil 之前的对象,nil 之后的对象会被抛弃!!!
nil nil是指一个不存在的OC实例对象指针,指的是OC实例对象指针的空值,也就是OC实例对象的空指针。...NSObject *object = nil; NSString *str = nil; NSURL *url = nil; id object = nil; Nil Nil...不过由于大部分代码中不需要引用Class类型的变量,所以Nil并不常用。...我们知道,在集合(NSArray、NSDictionary、NSSet)中是不可以存储nil值的,但是如果我们有存储空值的需求的话,可以使用NSNull来代替nil。...在NSArray中,使用NSNull来代替nil的案例: //错误写法:nil为数组结束标志,所以此时该数组的count=2,所以数组不能存储nil值。
nil、Nil、NULL、NSNull的区别 nil:指向一个对象的空指针 Nil:指向一个类的空指针 NULL:指向其他类型(如:基本类型、C类型)的空指针 NSNull:通常表示集合中的空值...举例: NSURL *url = nil; Class class = Nil; int *pointerInt = NULL; NSArray *array = [NSArray arrayWithObjects...为什么上面的array里面的空对象不直接用nil?...如果用nil,就会变成NSArray *array = [NSArray arrayWithObjects:[[NSObject alloc] init], nil, [[NSObject alloc...] init], [[NSObject alloc] init], nil];,那么数组到第二个位置就会结束。
nil { fmt.Println("The value of m is nil") } } 执行结果是: The value of s is nil The value...of m is nil 当一个切片的值为“nil”时,是可以对它进行添加数据等操作。...", s == nil) s = append(s, 1) fmt.Println("Is s a nil?...", s == nil) fmt.Println(s) } 执行结果是: The result is like this: Is s a nil? true Is s a nil?...a nil?
Go 接口:nil接口为什么不等于nil? 本文主要内容:深入了解接口类型的运行时表示层。...2.2 “动静皆备”的特性的好处 首先,接口类型变量在程序运行时可以被赋值为不同的动态类型变量,每次赋值后,接口类型变量中存储的动态类型信息都会发生变化,这让 Go 语言可以像动态语言(比如 Python...接口类型的动静特性展示了其强大的一面,然而在日常使用中,对Gopher常常困惑与“nil 的 error 值不等于 nil”。下面我们来详细看一下。 三、nil error 值 !...未显式初始化的接口类型变量的值为nil,也就是这个变量的 _type/tab 和 data 都为 nil。...println("i = nil:", i == nil) println("err = nil:", err == nil) println("i = err:", i == err) } 运行这个函数
现在有这样两种赋值方式 a := (*interface{})(nil) var c interface{} c = (*interface{})(nil) a现在是啥 ?...(*interface{})(nil) 意思是把nil 类型转换为 *interface{}类型 a相当于 var a *interface{} = nil , a是个指针 , 指向了nil..., 所以a是nil c现在是啥 ?...data都是nil时 , 空接口才是nil , 所以c不是nil a := (*interface{})(nil) log.Printf("%v\n", a == nil)...var c interface{} c = (*interface{})(nil) log.Printf("%v\n", c == nil) ?
= nil {return x.A}return nil}func TestNil(t *testing.T) {var s *Messagevar v interface{} = sfmt.Println...(v == nil) // #=> falsefmt.Println(s.GetA().GetA().GetA() == nil) // #=> true}问题一...:s是nil,为什么赋值给v就不是nil了?...问题二:s是nil,v不是nil,为什么s还等于v?问题三:s.GetA()返回的是nil,为什么nil还能继续调用GetA()方法?...= nil) // #=> true}这里和上面是相同的问题,即返回的nil为什么不等于nil?
var ptr *int if ptr == nil { fmt.Println("ptr is nil") } 2....var s []int if s == nil { fmt.Println("s is nil") } 3. 映射(Maps) nil 映射表示一个空映射,其中不包含任何键值对。...var m map[string]int if m == nil { fmt.Println("m is nil") } 4....var ch chan int if ch == nil { fmt.Println("ch is nil") } 5....var f func(int) int if f == nil { fmt.Println("f is nil") } nil 在 Go 中用于表示无效或未分配状态。
像C这样的可以声明一个变量,然后赋值,而像Python,声明和赋值甚至可以写成一起。 指针 了解了内存地址和变量的关系,我们再看看指针。可以把指针看成是一种“类型”,这种类型的值是一个内存地址。...) 指针变量的零值不是空子串,而是nil。...因此初始化为nil。...可是aPot的值是nil,但还没有赋值成地址,因此不能把一个子串赋值给一个nil值。此外,即使不是赋值,对nil的指针通过*读取也会报错,毕竟读取不到任何地址。...go会给引用类型初始化为nil,nil是不能直接赋值的。并且,map和数组指针还不一样,不能使用new开辟一个内存,然后再赋值。
可能很多同学,会认为结果是输出两个 nil。 为什么呢? 因为 f 和 a 都没初始化,都是 nil,所以循环遍历后肯定也是 nil。 如果你的答案也是这样,那就掉进坑里了。 答案是,啥都不会输出!...但是类型不是 nil。...() ---- item= item type: *struct {} ---- item= item type: item == nil ---- 你会发现之后最后...三、怎么判断值是否为 nil 我们在写代码时,最好是尽量避免这种代码,如果硬要这么写,那我们可以通过以下两种常见方式判 nil。...(func()); ok && v == nil { fmt.Println("item is nil") } if v, ok := item.
golang 中的 nil 是不同于其他语言的,为了更好的理解 nil,在此我将尝试一步一步揭示 nil 在 golang 中的一些操作和现象。...1. nil 是不能比较的 code-1 Play package main import ( "fmt" ) func main() { fmt.Println(nil==nil...on nil 这点和 python 等动态语言是不同的,在 python 中,两个 None 值永远相等。...("%T", nil) print(nil) } code-2 输出 tmp/sandbox379579345/main.go:9: use of untyped nil...) (*int)(nil) (chan int)(nil) []int(nil) (func())(nil) zero value 是 go 中变量在声明之后但是未初始化被赋予的该类型的一个默认值
= nil { // do something.... } 当出现不等于nil的时候,说明出现某些错误了,需要我们对这个错误进行一些处理,而如果等于nil说明运行正常。那什么是nil呢?...slices -> nil maps -> nil channels -> nil functions -> nil interfaces -> nil 举个例子,当你定义了一个struct: type...nil并不是Go的关键字之一,你甚至可以自己去改变nil的值: var nil = errors.New("hi") 这样是完全可以编译得过的,但是最好不要这样子去做。...nil有什么用 在了解了什么是nil之后,再来说说nil有什么用。...只有当类型和值都是nil的时候,才等于nil。
在go中,对类型明确的对象,要判定它是不是nil简单 func test1(v *teststr) { if v == nil { fmt.Println("value is nil...(*teststr) fmt.Println("type is ok:", ok) if i == nil { fmt.Println("interface is nil...nilVal *teststr test(nilVal) // value is nil 传入真正的nil test(nil) // type is ok false \n interface...is nil 另外,如果interface传入真正的nil,对它做任何类型断言,都是失败的。...结论: 对于函数,传入值是interface,想判定它是不是nil: func test(i interface{}) bool { // 判定是不是真正的nil if i == nil
: ", b == nil)}func isNil(x any) bool {return x == nil}程序运行结果:isNil: trueisNil: false b == nil: true...此外,还直接打印了 b == nil 的值,用于对比。根据运行结果可知,在 isNil 函数里 a == nil 成立,而 b == nil 不成立,但在外部,b == nil 成立。...只有当接口的 类型部分 和 值部分 都为 nil 时,该接口才被认为是 nil。...反射机制检查 nil既然 == 或 != 这两种方式不能完全判断接口类型是否为 nil,那么该怎么解决这个问题呢?答案是使用 反射。通过反射,我们可以直接判断某个变量值是否为 nil。...只有当 类型部分 和 值部分 都为 nil 时,接口才被认为是 nil。解决方案:使用反射机制可以准确判断一个接口类型变量是否为 nil。
v=ynoY2xz-F8s,Slides:https://speakerdeck.com/campoy/understanding-nil nil是什么 就结果来说,nil是绝大部分Go中类型的初始值,...对接口来说,接口为nil代表着(nil,nil),因此如果声明了一个自珍并且把指针赋值给了接口,那类型就不为nil了(*Person,nil) type Person struct{ a int }...)//true var p *Person s = p fmt.Println(s == nil)//false,尽管值依旧为nil,但是类型不为nil } 什么时候nil不是nil nil可以是一个...=nil || b!=nil{ select{ case v,ok := <-a: if !...对于管道来说,比较需要注意的是对已经关闭的管道和nil的管道写入和读取等操作时与正常管道的差异。 对于map和其他类型来说,需要注意的是报错,比如nil切片的越界错误和nil映射表的读取错误哦。
接下来,顺便总结一下nil的使用 实际运用nil nil 是go语言中预先定义的标识符,不是关键字或保留字。 我们可以直接使用nil,而不用声明它。...而且我们可以定义一个名称为 nil 的变量,比如下面这样: var nil = errors.New("nil") fmt.Printf("%#v\n", nil)//&errors.errorString...默认值nil (重点记住) 在go语言中: 布尔类型的零值(初始值)为 false 数值类型的零值为 0 字符串类型的零值为空字符串"" 除此之外其它类型的默认值为nil,nil可以代表下面这些类型的零值...不同类型的nil值占用的内存大小可能是不一样的 一个类型的所有的值的内存布局都是一样的。nil也不例外。nil的大小一致与同类型中的非nil类型的值的大小一样大。...} } 如果类型T的零值是用预先定义的nil来表示的话,*new(T)产生一个nil T类型的值 //如果类型T的零值是用预先定义的nil来表示的话,*new(T)产生一个nil T类型的值 package
golang的nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。nil是预先说明的标识符,也即通常意义上的关键字。...由于nil是untyped(无类型),而又将nil赋值给了变量val,所以val实际上存储的是(nil, nil)。因此很容易就知道val和nil的相等比较是为true的。...也就是说变量val的底层结构肯定不为(nil, nil),因此它和nil的相等比较总是为false。 上面的讨论都是在围绕值类型来进行的。...关于(*interface{})(nil)还有一些要注意的地方。这里仅仅是拿(*interface{})(nil)来举例,对于(*int)(nil)、(*byte)(nil)等等来说是一样的。...not nil") } } 很显然,无论该指针的值是什么:(*interface{}, nil),这样的接口值总是非nil的,即使在该指针的内部为nil。
领取专属 10元无门槛券
手把手带您无忧上云