首頁 >後端開發 >Golang >go語言型別斷言是啥

go語言型別斷言是啥

青灯夜游
青灯夜游原創
2023-01-12 10:57:315134瀏覽

在go語言中,類型斷言是一個使用在介面值上的操作,用於檢查介面類型變數所持有的值是否實現了期望的介面或特定的類型,語法為「value, ok := x.(T)」。透過型別斷言可以做到的事:1、檢查i是否為nil;2、檢查i所儲存的值是否為某個型別。

go語言型別斷言是啥

本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。

斷言是什麼?

斷言是程式設計術語,表示為一些布林表達。在編寫程式碼時,我們總是會做出一些假設,斷言就是用於在程式碼中捕捉這些假設。簡單的來理解斷言的話就是判斷的意思。所以在Go中類型斷言我們就可以理解成對類型的判斷。

類型斷言介紹

類型斷言(Type Assertion)是使用在介面值上的操作,用於檢查介面類型變數所持有的值是否實現了期望的介面或具體的類型。

在Go語言中類型斷言的語法格式如下:

value, ok := x.(T)

其中,x 表示一個介面的類型,T 表示一個特定的類型(也可為介面類型)。

此斷言表達式會傳回x 的值(也就是value)和一個布林值(也就是ok),可根據該布林值判斷x 是否為T 類型:

  • 如果T 是具體某個類型,型別斷言會檢查x 的動態型別是否等於具體型別T。如果檢查成功,則類型斷言傳回的結果是 x 的動態值,其類型是 T。

  • 如果 T 是介面類型,類型斷言會檢查 x 的動態類型是否滿足 T。如果檢查成功,x 的動態值不會被提取,回傳值是一個類型為 T 的介面值。

  • 無論 T 是什麼類型,如果 x 是 nil 介面值,則類型斷言都會失敗。

在Go中型別斷言主要有兩種形式

  • #變數.(型別)。例如:i.(int)

  • 變數,bool = 變數.(型別)。例如:num,ok = i.(int)。 ok表示判斷類型是否成功的意思。

類型斷言的用法

#透過型別斷言可以做到以下幾件事

  • #檢查i 是否為nil

  • 檢查i 儲存的值是否為某個型別

具體的使用方式有兩種:

第一種:

t := i.(T)

這個表達式可以斷言一個介面物件(i)裡不是nil,且介面物件(i)儲存的值的類型是T,如果斷言成功,就會傳回值給t,如果斷言失敗,就會觸發panic。

來寫段程式碼試驗一下

package main

import "fmt"

func main() {
    var i interface{} = 10
    t1 := i.(int)
    fmt.Println(t1)

    fmt.Println("=====分隔线=====")

    t2 := i.(string)
    fmt.Println(t2)
}

運行後輸出如下,可以發現在執行第二次斷言的時候失敗了,並且觸發了panic

10
=====分隔线=====
panic: interface conversion: interface {} is int, not string

goroutine 1 [running]:
main.main()
        E:/GoPlayer/src/main.go:12 +0x10e
exit status 2

如果要斷言的介面值是nil,那我們來看看也是不是也如預期一樣會觸發panic

package main

func main() {
    var i interface{} // nil
    var _ = i.(interface{})
}

#輸出如下,確實是會觸發panic

panic: interface conversion: interface is nil, not interface {}

goroutine 1 [running]:
main.main()
        E:/GoPlayer/src/main.go:5 +0x34
exit status 2

第二種

t, ok:= i.(T)

和上面一樣,這個表達式也是可以斷言一個介面物件(i)裡不是nil,並且介面物件(i)儲存的值的類型是T,如果斷言成功,就會返回其型別給t,且此時ok 的值為true,表示斷言成功。

如果介面值的類型,並不是我們所斷言的T,就會斷言失敗,但和第一種表達式不同的事,這個不會觸發panic,而是將ok 的值設為false ,表示斷言失敗,此時t 為T 的零值。

稍微修改下上面的例子,如下

package main

import "fmt"

func main() {
    var i interface{} = 10
    t1, ok := i.(int)
    fmt.Printf("%d-%t\n", t1, ok)

    fmt.Println("=====分隔线1=====")

    t2, ok := i.(string)
    fmt.Printf("%s-%t\n", t2, ok)

    fmt.Println("=====分隔线2=====")

    var k interface{} // nil
    t3, ok := k.(interface{})
    fmt.Println(t3, "-", ok)

    fmt.Println("=====分隔线3=====")
    k = 10
    t4, ok := k.(interface{})
    fmt.Printf("%d-%t\n", t4, ok)

    t5, ok := k.(int)
    fmt.Printf("%d-%t\n", t5, ok)
}

運行後輸出如下,可以發現在執行第二次斷言的時候,雖然失敗了,但並沒有觸發了 panic。

10-true
=====分隔线1=====
-false
=====分隔线2=====
<nil> - false
=====分隔线3=====
10-true
10-true

上面這段輸出,你要注意的是第二個斷言的輸出在-false  之前並不是有沒有輸出任何t2 的值,而是由於斷言失敗,所以t2 得到的是string 的零值也是"" ,它是零長度的,所以你看不到其輸出。

Type Switch

如果需要區分多種類型,可以使用 type switch 斷言,這個將會比一個一個進行類型斷言更簡單、直接、更有效率。

package main

import "fmt"

func findType(i interface{}) {
    switch x := i.(type) {
    case int:
        fmt.Println(x, "is int")
    case string:
        fmt.Println(x, "is string")
    case nil:
        fmt.Println(x, "is nil")
    default:
        fmt.Println(x, "not type matched")
    }
}

func main() {
    findType(10)      // int
    findType("hello") // string

    var k interface{} // nil
    findType(k)

    findType(10.23) //float64
}

輸出如下

10 is int
hello is string
<nil> is nil
10.23 not type matched

額外說明:

  • #如果你的值是nil,那麼符合的是case nil
  • #如果你的值在switch-case 裡並沒有匹配對應的類型,那麼走的是default 分支

【相關推薦:Go影片教學程式教學

以上是go語言型別斷言是啥的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn