「インターフェイスへのポインタがnil nilのインターフェイスではありません含まれている」行くピットを打ちます

最近、プロジェクト内の深い穴に足を踏み入れた - あなたは非常にこの文を理解していない場合、次のコード例では深刻な表情は、避けることが推奨され、要約の下で共有するために「Golangは、インターフェイスへのポインタがnil nilのインターフェイスではありません含まれています」コードを書くときにピットをステッピング後。

の例

まず一緒にコードを見て、あなたはそれに問題がない感じ?

type IPeople interface {
    hello()
}
type People struct {
}

func (p *People) hello() {
    fmt.Println("github.com/meetbetter")
}

func errFunc1(in int) *People {
    if in == 0 {
        fmt.Println("importantFunc返回了一个nil")
        return nil
    } else {
        fmt.Println("importantFunc返回了一个非nil值")
        return &People{}
    }

}

func main() {
    var i IPeople

    in := 0

    i = errFunc1(in)

    if i == nil {

        fmt.Println("哈,外部接收到也是nil")
    } else {

        fmt.Println("咦,外部接收到不是nil哦")
        fmt.Printf("%v, %T\n", i, i)
    }

}

このコードの結果は次のとおりです。

importantFunc返回了一个nil
咦,外部接收到不是nil哦
<nil>, *main.People

主な機能で見ることができる受信した値がnilでない返し、明らかerrFunc1()関数は、それがゼロに受信されない理由にはnil、主な機能を返しますか?
nilに割り当て:これは、ある*Peopleその後する*Peopleインターフェイスに割り当てられ、*Peopleゼロポインタが指しているそのものであるが、唯一のインタフェースでゼロであるが、インタフェースに割り当てられている情報インタフェースの種類*main.Peopleので、むしろゼロよりこのインターフェースはゼロではありません。
はい、2つの情報を含むインターフェイスタイプをgolang -タイプ情報と価値情報は、唯一のインタフェースタイプは値のみインターフェイスにnil nilで結合され、基礎となる実装インターフェイスは、後でソースを参照し分析することができます。

のは、インターフェイスの戻り値を直接nilのインタフェースに割り当てられているに対処するための正しい方法を見てみましょう:


func rightFunc(in int) IPeople {
    if in == 0 {
        fmt.Println("importantFunc返回了一个nil")
        return nil
    } else {
        fmt.Println("importantFunc返回了一个非nil值")
        return &People{}
    }

}

例二

次のコードは、明確に示して一个包含nil指针的接口不是nil接口結論を:

type IPeople interface {
    hello()
}
type People struct {
}

func (p *People) hello() {
    fmt.Println("github.com/meetbetter")
}

//错误:将nil的people给空接口后接口就不为nil,因为interface中的value为nil但type不为nil
func errFunc() *People {
    var p *People

    return p
}

//正确处理返回nil给接口的方式:直接将nil赋给interface
func rightFunc() IPeople {
    var p *People

    return p
}
func main() {

    if errFunc() == nil {

        fmt.Println("对了哦,外部接收到也是nil")
    } else {

        fmt.Println("错了咦,外部接收到不是nil哦")

    }

    if rightFunc() == nil {

        fmt.Println("对了哦,外部接收到也是nil")
    } else {

        fmt.Println("错了咦,外部接收到不是nil哦")

    }

}

出力:

对了哦,外部接收到也是nil
错了咦,外部接收到不是nil哦

インタフェース基礎となる実装

参照記事から次のアノテーション情報は、ゼロであるデータポイントは、インタフェースを表していない場合であっても、中間層構造よりITAB eFace、ITAB _type情報記憶部と、[]楽しい方法のiface基底実装インターフェースから見ることができますnilは、だけでなく、_type情報を検討してください。

type eface struct {      //空接口
    _type *_type         //类型信息
    data  unsafe.Pointer //指向数据的指针(go语言中特殊的指针类型unsafe.Pointer类似于c语言中的void*)
}
type iface struct {      //带有方法的接口
    tab  *itab           //存储type信息还有结构实现方法的集合
    data unsafe.Pointer  //指向数据的指针(go语言中特殊的指针类型unsafe.Pointer类似于c语言中的void*)
}
type _type struct {
    size       uintptr  //类型大小
    ptrdata    uintptr  //前缀持有所有指针的内存大小
    hash       uint32   //数据hash值
    tflag      tflag
    align      uint8    //对齐
    fieldalign uint8    //嵌入结构体时的对齐
    kind       uint8    //kind 有些枚举值kind等于0是无效的
    alg        *typeAlg //函数指针数组,类型实现的所有方法
    gcdata    *byte
    str       nameOff
    ptrToThis typeOff
}
type itab struct {
    inter  *interfacetype  //接口类型
    _type  *_type          //结构类型
    link   *itab
    bad    int32
    inhash int32
    fun    [1]uintptr      //可变大小 方法集合
}

より完全なコード終えているGolangプロジェクトGithub-を学ぶためのコード例に従ってください

参考記事:
golang最初のピット

議論では「ポインタインタフェースはインタフェースゼロnilでない含まれています」

おすすめ

転載: www.cnblogs.com/CodeWithTxT/p/11297300.html