61.笔记go语言——Go语言的nil值和nil

来源:互联网 发布:推广优化软件 编辑:程序博客网 时间:2024/05/16 05:29

61.笔记go语言——Go语言的nil值和nil

Nil

在golang中,nil只能赋值给指针、channel、func、interface、map或slice类型的变量。如果未遵循这个规则,则会引发panic。

接口是什么?

golang语言的接口有其独到之处:只要类型T的公开方法完全满足接口I的要求,就可以把类型T的对象用在需要接口I的地方。这种做法的学名叫做StructuralTyping,有人也把它看作是一种静态的Duck Typing。所谓类型T的公开方法完全满足接口I的要求,也即是类型T实现了接口I所规定的一组成员。

示例代码

packagemain

 

import(

    "fmt"

)

 

funcmain(){

    varvalinterface{}=nil

    ifval==nil{

        fmt.Println("valisnil")

    }else{

        fmt.Println("valisnotnil")

    }

}

执行:

val is nil

变量val是interface类型,它的底层结构必然是(type,data)。由于nil是untyped(无类型),而又将nil赋值给了变量val,所以val实际上存储的是(nil, nil)。因此很容易就知道val和nil的相等比较是为true的。

对于将任何其它有意义的值类型赋值给val,都导致val持有一个有效的类型和数据。也就是说变量val的底层结构肯定不为(nil, nil),因此它和nil的相等比较总是为false。

示例二

代码:

packagemain
 
import(
    "fmt"
)
 
funcmain(){
    varvalinterface{}=(*interface{})(nil)
    //val=(*int)(nil)
    ifval==nil{
        fmt.Println("valisnil")
    }else{
        fmt.Println("valisnotnil")
    }
}

interface类型的变量和nil的相等比较出现最多的地方应该是error接口类型的值与nil的比较。

例如:

packagemain
 
import(
    "fmt"
)
 
typedatastruct{}
 
func(this*data)Error()string{return""}
 
functest()error{
    varp*data=nil
    returnp
}
 
funcmain(){
    vareerror=test()
    ife==nil{
        fmt.Println("eisnil")
    }else{
        fmt.Println("eisnotnil")
    }
}

error是一个接口类型,test方法中返回的指针p虽然数据是nil,但是由于它被返回成包装的error类型,也即它是有类型的。所以它的底层结构应该是(*data, nil),很明显它是非nil的。

error

Go的error是一个interface类型,error的nil问题和C语言的字符串类似。

在底层,interface作为两个成员实现:一个类型和一个值。该值被称为接口的动态值,它是一个任意的具体值,而该接口的类型则为该值的类型。对于 int 值3,一个接口值示意性地包含(int, 3)。

只有在内部值和类型都未设置时(nil, nil),一个接口的值才为 nil。特别是,一个 nil 接口将总是拥有一个 nil 类型。若我们在一个接口值中存储一个 int 类型的指针,则内部类型将为 int,无论该指针的值是什么:(*int,nil)。因此,这样的接口值会是非 nil 的,即使在该指针的内部为 nil。

Go作为一个强类型语言,不同类型之前必须要显示的转换(而且必须是基础类型相同)。这样可以回避很多类似C语言中因为隐式类型转换引入的bug。

但是,Go中interface是一个例外:type到interface和interface之间可能是隐式转换的。

                  在Go中使用error接口作为返回函数或方法的返回类型是很常见的。Error接口在标准库中被使用的非常频繁。

关于ERROR

Error接口的定义如下:

type error interface {
    Error() string
}

声明了一个Error方法,返回一个string.所以,任何实现Error方法的类型都可以作为error类型的值。

标准库同样定义了errorString ,如下:

type errorString struct {
    s string
}

我们可以发现类型和域都不是大写的,那说明他不可以直接直接访问。(大写的变量才是导出的)

然后是errorString结构实现了error接口如下:

func (e *errorString) Error() string {
    return e.s
}

 

 

 

 

友情链接

·      http://golang.org/doc/go_faq.html#nil_error

原创粉丝点击