<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] ## 四、interface ### (1) interface的賦值問題 > 以下代碼能編譯過去嗎?為什么? > test12.go ```go package main import ( "fmt" ) type People interface { Speak(string) string } type Stduent struct{} func (stu *Stduent) Speak(think string) (talk string) { if think == "love" { talk = "You are a good boy" } else { talk = "hi" } return } func main() { var peo People = Stduent{} think := "love" fmt.Println(peo.Speak(think)) } ``` 繼承與多態的特點 在golang中對多態的特點體現從語法上并不是很明顯。 我們知道發生多態的幾個要素: 1、有interface接口,并且有接口定義的方法。 2、有子類去重寫interface的接口。 3、有父類指針指向子類的具體對象 那么,滿足上述3個條件,就可以產生多態效果,就是,父類指針可以調用子類的具體方法。 所以上述代碼報錯的地方在`var peo People = Stduent{}`這條語句, `Student{}`已經重寫了父類`People{}`中的`Speak(string) string`方法,那么只需要用父類指針指向子類對象即可。 所以應該改成`var peo People = &Student{}` 即可編譯通過。(People為interface類型,就是指針類型) ### (2) interface的內部構造(非空接口iface情況) > 以下代碼打印出來什么內容,說出為什么。 > test14.go ```go package main import ( "fmt" ) type People interface { Show() } type Student struct{} func (stu *Student) Show() { } func live() People { var stu *Student return stu } func main() { if live() == nil { fmt.Println("AAAAAAA") } else { fmt.Println("BBBBBBB") } } ``` **結果** ```bash BBBBBBB ``` **分析:** 我們需要了解`interface`的內部結構,才能理解這個題目的含義。 interface在使用的過程中,共有兩種表現形式 一種為**空接口(empty interface)**,定義如下: ```go var MyInterface interface{} ``` 另一種為**非空接口(non-empty interface)**, 定義如下: ```go type MyInterface interface { function() } ``` 這兩種interface類型分別用兩種`struct`表示,空接口為`eface`, 非空接口為`iface`. ![](https://img.kancloud.cn/8b/9a/8b9ad730048aceb7d7b7e3cf4631ad64_1920x1080.jpeg) --- #### **空接口eface** 空接口eface結構,由兩個屬性構成,一個是類型信息_type,一個是數據信息。其數據結構聲明如下: ```go type eface struct { //空接口 _type *_type //類型信息 data unsafe.Pointer //指向數據的指針(go語言中特殊的指針類型unsafe.Pointer類似于c語言中的void*) } ``` **_type屬性**:是GO語言中所有類型的公共描述,Go語言幾乎所有的數據結構都可以抽象成 _type,是所有類型的公共描述,**type負責決定data應該如何解釋和操作,**type的結構代碼如下: ```go type _type struct { size uintptr //類型大小 ptrdata uintptr //前綴持有所有指針的內存大小 hash uint32 //數據hash值 tflag tflag align uint8 //對齊 fieldalign uint8 //嵌入結構體時的對齊 kind uint8 //kind 有些枚舉值kind等于0是無效的 alg *typeAlg //函數指針數組,類型實現的所有方法 gcdata *byte str nameOff ptrToThis typeOff } ``` **data屬性:** 表示指向具體的實例數據的指針,他是一個`unsafe.Pointer`類型,相當于一個C的萬能指針`void*`。 ![](https://img.kancloud.cn/a5/dc/a5dc4728aa922c8bf1bc25e5252cdf49_1920x1080.jpeg) --- #### 非空接口iface iface 表示 non-empty interface 的數據結構,非空接口初始化的過程就是初始化一個iface類型的結構,其中`data`的作用同`eface`的相同,這里不再多加描述。 ```go type iface struct { tab *itab data unsafe.Pointer } ``` iface結構中最重要的是itab結構(結構如下),每一個 `itab` 都占 32 字節的空間。itab可以理解為`pair<interface type, concrete type>` 。itab里面包含了interface的一些關鍵信息,比如method的具體實現。 ```go type itab struct { inter *interfacetype // 接口自身的元信息 _type *_type // 具體類型的元信息 link *itab bad int32 hash int32 // _type里也有一個同樣的hash,此處多放一個是為了方便運行接口斷言 fun [1]uintptr // 函數指針,指向具體類型所實現的方法 } ``` 其中值得注意的字段,個人理解如下: 1. `interface type`包含了一些關于interface本身的信息,比如`package path`,包含的`method`。這里的interfacetype是定義interface的一種抽象表示。 2. `type`表示具體化的類型,與eface的 *type類型相同。* 3. `hash`字段其實是對`_type.hash`的拷貝,它會在interface的實例化時,用于快速判斷目標類型和接口中的類型是否一致。另,Go的interface的Duck-typing機制也是依賴這個字段來實現。 4. `fun`字段其實是一個動態大小的數組,雖然聲明時是固定大小為1,但在使用時會直接通過fun指針獲取其中的數據,并且不會檢查數組的邊界,所以該數組中保存的元素數量是不確定的。 ![](https://img.kancloud.cn/bf/69/bf6927577682a3a1eadbef249ad3f24c_1920x1080.jpeg) --- 所以,People擁有一個Show方法的,屬于非空接口,People的內部定義應該是一個`iface`結構體 ```go type People interface { Show() } ``` ![](https://img.kancloud.cn/36/87/3687c0abd9da66c7ed58bbc2258cf00e_1920x1080.jpeg) ```go func live() People { var stu *Student return stu } ``` stu是一個指向nil的空指針,但是最后`return stu` 會觸發`匿名變量 People = stu`值拷貝動作,所以最后`live()`放回給上層的是一個`People insterface{}`類型,也就是一個`iface struct{}`類型。 stu為nil,只是`iface`中的data 為nil而已。 但是`iface struct{}`本身并不為nil. ![](https://img.kancloud.cn/af/13/af13c13498a74d3a9c90cf8cc208e4a0_1920x1080.jpeg) 所以如下判斷的結果為`BBBBBBB`: ```go func main() { if live() == nil { fmt.Println("AAAAAAA") } else { fmt.Println("BBBBBBB") } } ``` ### (3) interface內部構造(空接口eface情況) > 下面代碼結果為什么? ```go func Foo(x interface{}) { if x == nil { fmt.Println("empty interface") return } fmt.Println("non-empty interface") } func main() { var p *int = nil Foo(p) } ``` **結果** ```bash non-empty interface ``` **分析** 不難看出,`Foo()`的形參`x interface{}`是一個空接口類型`eface struct{}`。 ![](https://img.kancloud.cn/39/37/3937d83d64ac00a29365513f1e9bece3_1920x1080.jpeg) 在執行`Foo(p)`的時候,觸發`x interface{} = p`語句,所以此時 x結構如下。 ![](https://img.kancloud.cn/56/f5/56f50ff0127db53e6d28d3ce081e7520_1920x1080.jpeg) 所以 x 結構體本身不為nil,而是data指針指向的p為nil。 --- ### (4) inteface{}與*interface{} > ABCD中哪一行存在錯誤? > test15.go ```go type S struct { } func f(x interface{}) { } func g(x *interface{}) { } func main() { s := S{} p := &s f(s) //A g(s) //B f(p) //C g(p) //D } ``` **結果** ```bash B、D兩行錯誤 B錯誤為: cannot use s (type S) as type *interface {} in argument to g: *interface {} is pointer to interface, not interface D錯誤為:cannot use p (type *S) as type *interface {} in argument to g: *interface {} is pointer to interface, not interface ``` 看到這道題需要第一時間想到的是Golang是強類型語言,interface是所有golang類型的父類 函數中`func f(x interface{})`的`interface{}`可以支持傳入golang的任何類型,包括指針,但是函數`func g(x *interface{})`只能接受`*interface{}`
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看