亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

接口可以是 nil 類型,但這并不意味著它們是 nil?

接口可以是 nil 類型,但這并不意味著它們是 nil?

Go
絕地無雙 2022-08-01 16:56:19
我寫了一些代碼,實際上就是這樣做的:package mainimport "fmt"type SomeInterface interface {    Retrieve(identifier string)}type SomeStruct struct {}func (r SomeStruct) Retrieve(identifier string) {    fmt.Println("identifier ", identifier)}type Handler struct {    Name string    SomeObject SomeInterface}func main() {    var someStruct *SomeStruct    var h = Handler{        Name: "helo",        SomeObject: someStruct,    }    fmt.Printf("before %+v\r\n", h.SomeObject)    if h.SomeObject == nil {        fmt.Printf("during %+v\r\n", h.SomeObject)    }    fmt.Printf("after %+v\r\n", h.SomeObject)}請有人向我解釋為什么上面的輸出是:before <nil>after <nil>我一直在閱讀有關類型的接口的信息,但在這種情況下,我將接口分配給了一個尚未分配的指針,因此我本來以為該接口并且我會看到 - 唉,事實并非如此。nil== nilduring <nil>
查看完整描述

3 回答

?
鳳凰求蠱

TA貢獻1825條經驗 獲得超4個贊

接口值是一個簡單的數據結構,由兩部分組成:類型和基礎值。因此,接口值本身可以是 ,或者接口值可以存在,但基礎值可以是 。例如:nilnil


var x interface{} = nil // x is nil

var y interface{} = (interface{})(nil) // y is a interface{}, which *contains* nil

這在某些概念上與此差異相似:


var x []*int = nil // x is nil

var y []*int = []*int{nil} // y is a []*int, which *contains* nil

fmt.Printf由于接口格式化輸出的方式,掩蓋了接口情況下的差異;如果您愿意,可以使用反射更清楚地看到差異。


查看完整回答
反對 回復 2022-08-01
?
眼眸繁星

TA貢獻1873條經驗 獲得超9個贊

在 Go 中,引用某些接口的實現者的變量可以具有多種類型。它可以是類型(是的,可以描述類型以及值),它可以是其實現者之一的類型,也可以是指向其實現者之一的指針的類型。默認情況下,引用接口的變量的類型為 。一旦你向它分配了一些東西(除了它本身),它就會采用你分配給它的東西的類型(同樣,要么是它的實現者之一的類型,要么是指向其中一種類型的指針)。<nil>nilnilnil


可以使用 打印接口變量的類型,并使用 %v 打印其值:%T


func main() {

    var i SomeInterface

    fmt.Printf("%T, %v\n", i, i) // Prints <nil>, <nil>

    

    var someStruct SomeStruct

    i = someStruct

    fmt.Printf("%T, %v\n", i, i) // Prints main.SomeStruct, {}

    

    var someStructPtr *SomeStruct

    i = someStructPtr

    fmt.Printf("%T, %v\n", i, i) // Prints *main.SomeStruct, <nil>

}

現在,每當您比較時,只有當兩個操作數的類型和值都匹配時,比較才會被計算為 true。在你的情況下,的值顯然是(畢竟,的值肯定是 ,并且你將其值存儲在 中)。的類型,根據我剛才解釋的內容,必須是 。的價值顯然是。h.SomeObject == nilh.SomeObject<nil>someStruct<nil>h.SomeObjecth.SomeObject*SomeStructnil<nil>


但是,是什么類型?nil


好吧,可以采用多種類型,編譯器必須決定每種用法應該采用哪種類型。當涉及到比較和分配時,它只是簡單地采用它被比較或分配的東西的類型。例如,如果要將整數指針與 進行比較,則在這種情況下,類型為 。nilnilnil*int


但所有這些都必須在編譯時決定,并且引用接口的變量可以在運行時更改類型。那么,當您將引用接口的變量與 進行比較時,在這種情況下,編譯器會為操作數提供什么類型呢?好吧,它給了它唯一合理的類型, .nilnil<nil>


最后一個示例,請考慮以下代碼:


func main() {

    var p *SomeStruct = nil // = nil is optional; pointers default to nil

    var i SomeInterface = p

    printf("%t\n", p == nil) // Prints true

    printf("%t\n", p == i) // Prints true

    printf("%t\n", i == nil) // Prints false

}

p == nil為 true,因為 is 的類型帶有值 ,并且(在本例中)也是具有值的類型。p*SomeStruct<nil>nil*SomeStruct<nil>


p == i是 true,因為 也是具有值的類型(它只是存儲 的類型和值)。i*SomeStruct<nil>p


但是,是 false,因為在這種情況下,采用的類型而不是 。i == nilnil<nil>*SomeStruct


解決這個問題的方法是永遠不要在接口引用變量中存儲一些有價值的東西,除了它本身。這樣,每當接口引用變量的值為 時,其類型也將是 ,并且比較將按預期工作。因此,您經常會看到如下所示的代碼:<nil>nil<nil><nil>nil


if p == nil {

    i = nil

} else {

    i = p

}


查看完整回答
反對 回復 2022-08-01
?
aluckdog

TA貢獻1847條經驗 獲得超7個贊

SomeObject 不是 nil,它只是指向 SomeStruct,它是 nil。

我認為混亂是fmt。Printf打印這種情況,因為它遵循指針,最終結果是零。<nil>


查看完整回答
反對 回復 2022-08-01
  • 3 回答
  • 0 關注
  • 147 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號