Go基礎系列:介面類型探測和type-switch

來源:互聯網
上載者:User

標籤:case   def   receive   cas   radius   儲存   return   pack   func   

介面類型探測:類型斷言

介面執行個體中儲存了實現介面的類型執行個體,類型的執行個體有兩種:實值型別執行個體和指標類型執行個體。在程式運行過程中,介面執行個體儲存的執行個體類型可能會動態改變。例如:

// ins是介面執行個體var ins Shaper// ins儲存實值型別的執行個體ins = c1// 一段時間後......// ins儲存指標類型的執行個體,儲存的類型發生改變ins = c2// 一段時間後...// ins可能儲存另一個類型執行個體ins = s1

所以,需要一種探測介面執行個體所儲存的是實值型別還是指標類型。

探測的方法是:ins.(Type)ins.(*Type)。它們有兩個傳回值,第二個傳回值是ok傳回值,布爾類型,第一個傳回值是探測出的類型。也可以只有一個傳回值:探測出的類型。

// 如果ins儲存的是實值型別的Type,則輸出if t, ok := ins.(Type); ok {    fmt.Printf("%T\n", v)}// 如果ins儲存的是指標類型的*Type,則輸出if t, ok := ins.(*Type); ok {    fmt.Printf("%T\n", v)}// 一個傳回值的探測t := ins.(Type)t := ins.(*Type)

以下是一個例子:

package mainimport "fmt"// Shaper 介面類型type Shaper interface {    Area() float64}// Square struct類型type Square struct {    length float64}// Square類型實現Shaper中的方法Area()func (s Square) Area() float64 {    return s.length * s.length}func main() {    var ins1, ins2, Shaper    // 指標類型的執行個體    s1 := new(Square)    s1.length = 3.0    ins1 = s1    if v, ok := ins1.(*Square); ok {        fmt.Printf("ins1: %T\n", v)    }    // 實值型別的執行個體    s2 := Square{4.0}    ins2 = s2    if v, ok := ins2.(Square); ok {        fmt.Printf("ins2: %T\n", v)    }}

上面兩個Printf都會輸出,因為它們的類型判斷都返回true。如果將ins2.(Square)改為ins2.(*Square),第二個Printf將不會輸出,因為ins2它儲存的是實值型別的執行個體。

特別需要注意的是,ins必須明確是介面執行個體。例如,以下前兩種聲明是有效,第三種推斷類型是錯誤的,因為它可能是介面執行個體,也可能是類型的執行個體副本。

var ins Shaper     // 正確ins := Shaper(s1)  // 正確ins := s1          // 錯誤

當ins不能確定是介面執行個體時,用它來進行測試,例如ins.(Square)將會報錯:

invalid type assertion:ins.(Square) (non-interface type (type of ins) on left)

它說明了左邊的ins是非介面類型(non-interface type)。

type Switch結構

switch流程式控制制結構還可以用來探測介面執行個體儲存的類型。這種結構稱為type-switch

用法如下:

switch v := ins.(type) {case *Square:    fmt.Printf("Type Square %T\n", v)case *Circle:    fmt.Printf("Type Circle %T\n", v)case nil:    fmt.Println("nil value: nothing to check?")default:    fmt.Printf("Unexpected type %T", v)}

其中ins.(type)中的小寫type是固定的詞語。

以下是一個使用樣本:

package mainimport (    "fmt")// Shaper 介面類型type Shaper interface {    Area() float64}// Circle struct類型type Circle struct {    radius float64}// Circle類型實現Shaper中的方法Area()func (c *Circle) Area() float64 {    return 3.14 * c.radius * c.radius}// Square struct類型type Square struct {    length float64}// Square類型實現Shaper中的方法Area()func (s Square) Area() float64 {    return s.length * s.length}func main() {    s1 := &Square{3.3}    whichType(s1)    s2 := Square{3.4}    whichType(s2)    c1 := new(Circle)    c1.radius = 2.3    whichType(c1)}func whichType(n Shaper) {    switch v := n.(type) {    case *Square:        fmt.Printf("Type Square %T\n", v)    case Square:        fmt.Printf("Type Square %T\n", v)    case *Circle:        fmt.Printf("Type Circle %T\n", v)    case nil:        fmt.Println("nil value: nothing to check?")    default:        fmt.Printf("Unexpected type %T", v)    }}

上面的type-switch中,之所以沒有加上case Circle,是因為Circle只實現了指標類型的receiver,根據Method Set對介面的實現規則,只有指標類型的Circle樣本才算是實現了介面Shaper,所以將實值型別的樣本case Circle放進type-switch是錯誤的。

Go基礎系列:介面類型探測和type-switch

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.