首頁  >  文章  >  後端開發  >  Go 的「類型斷言」方式背後的原因是什麼?

Go 的「類型斷言」方式背後的原因是什麼?

王林
王林轉載
2024-02-06 08:12:07952瀏覽

Go 的“类型断言”方式背后的原因是什么?

問題內容

我試圖理解這樣一個事實:golang 的類型斷言僅適用於明確定義為介面類型的變量,不適用於具體類型(即“string”、“int32”)等..)。

這是一個快速而簡單的程式碼範例,它說明了我困惑的根本原因:

package main

import "fmt"

// here we define an interface type:
type Shape interface {
    DoubleSize() int32
}

// here we define a new type which is really just an int32:
type Rect int32

// here we make "Rect" type above comply with the "Shape" interface by implementing the methods of that interface
// and so, since the interfaces in Go are implemented implicitly, this should make the "Rect" type an implicit instance of the "Shape" interface
func (theShape Rect) DoubleSize() int32 {
    return int32(theShape) * 2
}

// this function expects its "someShape" parameter to be of "Shape" type (or "the type that quacks like "Shape" interface does))
func whateverFunction(someShape Shape) int32 {
    return someShape.DoubleSize()
}

func main() {
    var newRect = Rect(5)
    // ^^ if this is instead written as "var newRect Shape = Rect(5)" no error with type assertion happens down the line

    whateverFunction(newRect) // the function works just fine because "newRect" implicitly implements the "Shape" interface — the one that this function expects to receive.  

    // !! but type assertion doesn't work on "newRect"
    v, ok := newRect.(Shape) // error: invalid operation: newRect (variable of type Rect) is not an interface
    if !ok {
        fmt.Println("type assertion failed")
        return
    }
    fmt.Println("This is v:", v)
}
正如這個問題的標題所暗示的,我無法理解實現類型斷言僅適用於接口類型背後的推理,並檢查分配給顯式實現該接口的變量的基礎值是否是我們在內部指定的值“.(t )”斷言方法。這讓我覺得「類型斷言」是一個無意的用詞不當,意味著它適用於所有類型,但不適用於,僅適用於介面類型。

我的意思是,這個語言設計決策背後顯然一定有一個原因,我認為這可能與慣用的golang 的編寫方式有關,但儘管我已經看到了關於這個問題的大量資源,他們從未具體說明原因。

對我來說有意義的原因是,如果go 程式應該“最好(我假設,因為顯式介面定義是可選的)”,用表示某些介面(行為)的所有變數編寫,因此定義一個出於清晰性和可讀性的目的,變數上的明確介面是有意義的。

但正如我所提到的,我從未見過任何資源具體說明為什麼「類型斷言」功能是如何在 go 中實現的,我希望您能幫助我澄清這種困惑。

-- upd 1 - 加入一些內容來澄清我的問題:

我認為,我的核心問題是關於原因(我不明白)類型斷言僅在顯式實現變數的介面時才起作用,而在隱式實作介面時則不起作用。

正如「whateverfunction」所示範的,程式碼確實考慮「newrect」來實作「shape」接口,或「成為「shape」介面的實作」(否則該函數將不會不適用於該變量,但確實如此),但類型斷言“.(t)”方法背後的程式碼將“newrect”視為“shape”介面的實作。

因此,如果 golang 中關於介面實現的考慮因素存在差異,我認為這樣的設計決策背後一定有一個原因(區分)。

這就是為什麼我提到到目前為止我能想到的唯一原因是這是否是一種讓人們以某種方式編寫 go 程式碼的方法。


正確答案


您可以查看Burak Serdar的答案 - 您可能會發現它更加簡潔和有幫助。儘管如此,我還是會發布整個推理鏈,最終讓我「點擊」了它:

|-> 當我們無法確定我們期望接收的資料的確切類型時,使用介面(因為,例如,作為使用者輸入的結果,程式中某個函數中的相同參數可能會接收不同類型的數據),但我們知道所提供的數據應該具有的確切行為。

^^ 因此,介面中儲存的值的實際類型在編譯時是未知的。 (否則,顯然,我們會在程式碼中指定它。)

| -> 因此,我們獲得類型斷言,以便能夠根據我們期望程式在執行期間提供的可能值來定義程式的行為。

|-> 因此,類型斷言僅適用於明確指定為介面類型的變量,而不適用於那些可能實現相同介面但未明確指定為介面類型的變數

是因為

當我們使用介面時,我們只在運行時需要這種類型斷言,因為我們不知道將發送到程式的資料的確切類型- 只有在使用介面時才需要這種類型斷言,因此類型斷言僅適用於明確指定為介面類型的類型,因為在所有其他情況下,資料類型都是已知的(允許編譯器隱式地假定變數實作介面- 因為它已經知道所涉及資料的所有資料類型)我們根本不需要對已知類型的資料使用類型斷言。

以上是Go 的「類型斷言」方式背後的原因是什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除