最近、プロジェクト内の深い穴に足を踏み入れた - あなたは非常にこの文を理解していない場合、次のコード例では深刻な表情は、避けることが推奨され、要約の下で共有するために「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最初のピット