Go的類型斷言解析


經常地我們對一個接口值的動態類型是不確定的,如方法的形參為接口類型時,此時就需要檢驗它是否符合我們需要的類型。
類型斷言是一個使用在接口值上的操作。

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

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

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

第二種如果斷言的類型T是一個接口類型,類型斷言x.(T)檢查x的動態類型是否滿足T接口。

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

注意:

  • 如果斷言的操作對象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()
}

 執行結果:

main.Person
xiaohua
xiaohua


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM