Go的類型斷言解析

常常地咱們對一個接口值的動態類型是不肯定的,如方法的形參爲接口類型時,此時就須要檢驗它是否符合咱們須要的類型。
類型斷言是一個使用在接口值上的操做。
html

若是對Golang的接口和接口值的概念不熟悉,看這裏:Go的接口總結
斷言類型的語法:x.(T),這裏x表示一個接口的類型,T表示一個類型(也可爲接口類型)。
一個類型斷言檢查一個接口對象x的動態類型是否和斷言的類型T匹配。
spa

類型斷言分兩種狀況:
第一種若是斷言的類型T是一個具體類型,類型斷言x.(T)就檢查x的動態類型是否和T的類型相同。
htm

  • 若是這個檢查成功了,類型斷言的結果是一個類型爲T的對象,該對象的值爲接口變量x的動態值。換句話說,具體類型的類型斷言從它的操做對象中得到具體的值。
  • 若是檢查失敗,接下來這個操做會拋出panic,除非用兩個變量來接收檢查結果,如:f, ok := w.(*os.File)

第二種若是斷言的類型T是一個接口類型,類型斷言x.(T)檢查x的動態類型是否知足T接口。
對象

  • 若是這個檢查成功,則檢查結果的接口值的動態類型和動態值不變,可是該接口值的類型被轉換爲接口類型T。換句話說,對一個接口類型的類型斷言改變了類型的表述方式,改變了能夠獲取的方法集合(一般更大),可是它保護了接口值內部的動態類型和值的部分。
  • 若是檢查失敗,接下來這個操做會拋出panic,除非用兩個變量來接收檢查結果,如:f, ok := w.(io.ReadWriter)

注意:
blog

  • 若是斷言的操做對象x是一個nil接口值,那麼不論被斷言的類型T是什麼這個類型斷言都會失敗。
  • 咱們幾乎不須要對一個更少限制性的接口類型(更少的方法集合)作斷言,由於它表現的就像賦值操做同樣,除了對於nil接口值的狀況。

示例代碼:接口

  

//===接口=====
type Tester interface {
	getName()string
}
type Tester2 interface {
	printName()
}
//===Person類型====
type Person struct {
	name string
}
func (p Person)getName() string {
	return p.name
}
func (p Person) printName() {
	fmt.Println(p.name)
}
//============
func main() {
	var t Tester
	t = Person{"xiaohua"}
	check(t)
}
func check(t Tester)  {
    //第一種狀況
	if f, ok1 := t.(Person);ok1 {
		fmt.Printf("%T\n%s\n",f,f.getName())
	}
    //第二種狀況
	if t, ok2 := t.(Tester2);ok2 {  //重用變量名t(無需從新聲明)
		check2(t) //若類型斷言爲true,則新的t被轉型爲Tester2接口類型,但其動態類型和動態值不變
	}
}
func check2(t Tester2)  {
	t.printName()
}

 執行結果:get

main.Person
xiaohua
xiaohuastring

相關文章
相關標籤/搜索