<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## 11.9.1 概念 **空接口或者最小接口**?不包含任何方法,它對實現不做任何要求: ~~~ type Any interface {} ~~~ 任何其他類型都實現了空接口(它不僅僅像?`Java/C#`?中?`Object`?引用類型),`any`?或?`Any`?是空接口一個很好的別名或縮寫。 空接口類似?`Java/C#`?中所有類的基類:?`Object`?類,二者的目標也很相近。 可以給一個空接口類型的變量?`var val interface {}`?賦任何類型的值。 示例 11.8 empty_interface.go: ~~~ package main import "fmt" var i = 5 var str = "ABC" type Person struct { name string age int } type Any interface{} func main() { var val Any val = 5 fmt.Printf("val has the value: %v\n", val) val = str fmt.Printf("val has the value: %v\n", val) pers1 := new(Person) pers1.name = "Rob Pike" pers1.age = 55 val = pers1 fmt.Printf("val has the value: %v\n", val) switch t := val.(type) { case int: fmt.Printf("Type int %T\n", t) case string: fmt.Printf("Type string %T\n", t) case bool: fmt.Printf("Type boolean %T\n", t) case *Person: fmt.Printf("Type pointer to Person %T\n", t) default: fmt.Printf("Unexpected type %T", t) } } ~~~ 輸出: ~~~ val has the value: 5 val has the value: ABC val has the value: &{Rob Pike 55} Type pointer to Person *main.Person ~~~ 在上面的例子中,接口變量?`val`?被依次賦予一個?`int`,`string`?和?`Person`?實例的值,然后使用?`type-swtich`?來測試它的實際類型。每個?`interface {}`?變量在內存中占據兩個字長:一個用來存儲它包含的類型,另一個用來存儲它包含的數據或者指向數據的指針。 例子 emptyint_switch.go 說明了空接口在?`type-swtich`?中聯合?`lambda`?函數的用法: ~~~ package main import "fmt" type specialString string var whatIsThis specialString = "hello" func TypeSwitch() { testFunc := func(any interface{}) { switch v := any.(type) { case bool: fmt.Printf("any %v is a bool type", v) case int: fmt.Printf("any %v is an int type", v) case float32: fmt.Printf("any %v is a float32 type", v) case string: fmt.Printf("any %v is a string type", v) case specialString: fmt.Printf("any %v is a special String!", v) default: fmt.Println("unknown type!") } } testFunc(whatIsThis) } func main() { TypeSwitch() } ~~~ 輸出: ~~~ any hello is a special String! ~~~ **練習 11.9**?simple_interface3.go: 繼續 練習11.2,在它中添加一個?`gI`?函數,它不再接受?`Simpler`?類型的參數,而是接受一個空接口參數。然后通過類型斷言判斷參數是否是?`Simpler`?類型。最后在?`main`?使用?`gI`?取代?`fI`?函數并調用它。確保你的代碼足夠安全。 ## [](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/11.9.md#1192-構建通用類型或包含不同類型變量的數組)11.9.2 構建通用類型或包含不同類型變量的數組 在 7.6.6 中我們看到了能被搜索和排序的?`int`?數組、`float`?數組以及?`string`?數組,那么對于其他類型的數組呢,是不是我們必須得自己編程實現它們? 現在我們知道該怎么做了,就是通過使用空接口。讓我們給空接口定一個別名類型?`Element`:`type Element interface{}` 然后定義一個容器類型的結構體?`Vector`,它包含一個?`Element`?類型元素的切片: ~~~ type Vector struct { a []Element } ~~~ `Vector`?里能放任何類型的變量,因為任何類型都實現了空接口,實際上?`Vector`?里放的每個元素可以是不同類型的變量。我們為它定義一個?`At()`?方法用于返回第?`i`?個元素: ~~~ func (p *Vector) At(i int) Element { return p.a[i] } ~~~ 再定一個?`Set()`?方法用于設置第?`i`?個元素的值: ~~~ func (p *Vector) Set(i int, e Element) { p.a[i] = e } ~~~ `Vector`?中存儲的所有元素都是?`Element`?類型,要得到它們的原始類型(unboxing:拆箱)需要用到類型斷言。TODO:The compiler rejects assertions guaranteed to fail,類型斷言總是在運行時才執行,因此它會產生運行時錯誤。 **練習 11.10**?min_interface.go / minmain.go: 仿照11.7中開發的?`Sorter`?接口,創建一個?`Miner`?接口并實現一些必要的操作。函數?`Min`?接受一個?`Miner`?類型變量的集合,然后計算并返回集合中最小的元素。 ## [](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/11.9.md#1193-復制數據切片至空接口切片)11.9.3 復制數據切片至空接口切片 假設你有一個?`myType`?類型的數據切片,你想將切片中的數據復制到一個空接口切片中,類似: ~~~ var dataSlice []myType = FuncReturnSlice() var interfaceSlice []interface{} = dataSlice ~~~ 可惜不能這么做,編譯時會出錯: ~~~ cannot use dataSlice (type []myType) as type []interface { } in assignment ~~~ 原因是它們倆在內存中的布局是不一樣的(參考?[官方說明](http://golang.org/doc/go_spec.html))。 必須使用?`for-range`?語句來一個一個顯式地復制: ~~~ var dataSlice []myType = FuncReturnSlice() var interfaceSlice []interface{} = make([]interface{}, len(dataSlice)) for ix, d := range dataSlice { interfaceSlice[i] = d } ~~~ ## 11.9.4 通用類型的節點數據結構 在10.1中我們遇到了諸如列表和樹這樣的數據結構,在它們的定義中使用了一種叫節點的遞歸結構體類型,節點包含一個某種類型的數據字段。現在可以使用空接口作為數據字段的類型,這樣我們就能寫出通用的代碼。下面是實現一個二叉樹的部分代碼:通用定義、用于創建空節點的?`NewNode`?方法,及設置數據的?`SetData`?方法. 示例 11.10 node_structures.go: ~~~ package main import "fmt" type Node struct { le *Node data interface{} ri *Node } func NewNode(left, right *Node) *Node { return &Node{left, nil, right} } func (n *Node) SetData(data interface{}) { n.data = data } func main() { root := NewNode(nil, nil) root.SetData("root node") // make child (leaf) nodes: a := NewNode(nil, nil) a.SetData("left node") b := NewNode(nil, nil) b.SetData("right node") root.le = a root.ri = b fmt.Printf("%v\n", root) // Output: &{0x125275f0 root node 0x125275e0} } ~~~ ## 11.9.5 接口到接口 一個接口的值可以賦值給另一個接口變量,只要底層類型實現了必要的方法。這個轉換是在運行時進行檢查的,轉換失敗會導致一個運行時錯誤:這是 'Go' 語言動態的一面,可以那它和?`Ruby`?和?`Python`?這些動態語言相比較。 假定: ~~~ var ai AbsInterface // declares method Abs() type SqrInterface interface { Sqr() float } var si SqrInterface pp := new(Point) // say *Point implements Abs, Sqr var empty interface{} ~~~ 那么下面的語句和類型斷言是合法的: ~~~ empty = pp // everything satisfies empty ai = empty.(AbsInterface) // underlying value pp implements Abs() // (runtime failure otherwise) si = ai.(SqrInterface) // *Point has Sqr() even though AbsInterface doesn’t empty = si // *Point implements empty set // Note: statically checkable so type assertion not necessary. ~~~ 下面是函數調用的一個例子: ~~~ type myPrintInterface interface { print() } func f3(x myInterface) { x.(myPrintInterface).print() // type assertion to myPrintInterface } ~~~ `x`?轉換為?`myPrintInterface`?類型是完全動態的:只要?`x`?的底層類型(動態類型)定義了?`print`?方法這個調用就可以正常運行。
                  <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>

                              哎呀哎呀视频在线观看