中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go語言接口和類型如的轉換方法

發布時間:2021-03-05 11:13:15 來源:億速云 閱讀:288 作者:小新 欄目:編程語言

小編給大家分享一下Go語言接口和類型如的轉換方法,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

  Go語言中使用接口斷言(type assertions)將接口轉換成另外一個接口,也可以將接口轉換為另外的類型。接口的轉換在開發中非常常見,使用也非常頻繁。

  類型斷言的格式

  類型斷言是一個使用在接口值上的操作。語法上它看起來像 i.(T) 被稱為斷言類型,這里 i 表示一個接口的類型和 T 表示一個類型。一個類型斷言檢查它操作對象的動態類型是否和斷言的類型匹配。

  類型斷言的基本格式如下:

  t := i.(T)

  其中,i 代表接口變量,T 代表轉換的目標類型,t 代表轉換后的變量。

  這里有兩種可能。第一種,如果斷言的類型 T 是一個具體類型,然后類型斷言檢查 i 的動態類型是否和 T 相同。如果這個檢查成功了,類型斷言的結果是 i 的動態值,當然它的類型是 T。換句話說,具體類型的類型斷言從它的操作對象中獲得具體的值。如果檢查失敗,接下來這個操作會拋出 panic。例如:

  var w io.Writer

  w = os.Stdout

  f := w.(*os.File) // 成功: f == os.Stdout

  c := w.(*bytes.Buffer) // 死機:接口保存*os.file,而不是*bytes.buffer

  第二種,如果相反斷言的類型 T 是一個接口類型,然后類型斷言檢查是否 i 的動態類型滿足 T。如果這個檢查成功了,動態值沒有獲取到;這個結果仍然是一個有相同類型和值部分的接口值,但是結果有類型 T。換句話說,對一個接口類型的類型斷言改變了類型的表述方式,改變了可以獲取的方法集合(通常更大),但是它保護了接口值內部的動態類型和值的部分。

  在下面的第一個類型斷言后,w 和 rw 都持有 os.Stdout 因此它們每個有一個動態類型 *os.File,但是變量 w 是一個 io.Writer 類型只對外公開出文件的 Write 方法,然而 rw 變量也只公開它的 Read 方法。

  var w io.Writer

  w = os.Stdout

  rw := w.(io.ReadWriter) // 成功:*os.file具有讀寫功能

  w = new(ByteCounter)

  rw = w.(io.ReadWriter) // 死機:*字節計數器沒有讀取方法

  如果斷言操作的對象是一個 nil 接口值,那么不論被斷言的類型是什么這個類型斷言都會失敗。幾乎不需要對一個更少限制性的接口類型(更少的方法集合)做斷言,因為它表現的就像賦值操作一樣,除了對于 nil 接口值的情況。

  如果 i 沒有完全實現 T 接口的方法,這個語句將會觸發宕機。觸發宕機不是很友好,因此上面的語句還有一種寫法:

  t,ok := i.(T)

  這種寫法下,如果發生接口未實現時,將會把 ok 置為 false,t 置為 T 類型的 0 值。正常實現時,ok 為 true。這里 ok 可以被認為是:i 接口是否實現 T 類型的結果。

  將接口轉換為其他接口

  實現某個接口的類型同時實現了另外一個接口,此時可以在兩個接口間轉換。

  鳥和豬具有不同的特性,鳥可以飛,豬不能飛,但兩種動物都可以行走。如果使用結構體實現鳥和豬,讓它們具備自己特性的 Fly() 和 Walk() 方法就讓鳥和豬各自實現了飛行動物接口(Flyer)和行走動物接口(Walker)。

  將鳥和豬的實例創建后,被保存到 interface{} 類型的 map 中。interface{} 類型表示空接口,意思就是這種接口可以保存為任意類型。對保存有鳥或豬的實例的 interface{} 變量進行斷言操作,如果斷言對象是斷言指定的類型,則返回轉換為斷言對象類型的接口;如果不是指定的斷言類型時,斷言的第二個參數將返回 false。例如下面的代碼:

  var obj interface = new(bird)

  f, isFlyer := obj.(Flyer)

  代碼中,new(bird) 產生 *bird 類型的 bird 實例,這個實例被保存在 interface{} 類型的 obj 變量中。使用 obj.(Flyer) 類型斷言,將 obj 轉換為 Flyer 接口。f 為轉換成功時的 Flyer 接口類型,isFlyer 表示是否轉換成功,類型就是 bool。

  下面是詳細的代碼(代碼1):

 package main
  import "fmt"
  // 定義飛行動物接口
  type Flyer interface {
  Fly()
  }
  // 定義行走動物接口
  type Walker interface {
  Walk()
  }
  // 定義鳥類
  type bird struct {
  }
  // 實現飛行動物接口
  func (b *bird) Fly() {
  fmt.Println("bird: fly")
  }
  // 為鳥添加Walk()方法, 實現行走動物接口
  func (b *bird) Walk() {
  fmt.Println("bird: walk")
  }
  // 定義豬
  type pig struct {
  }
  // 為豬添加Walk()方法, 實現行走動物接口
  func (p *pig) Walk() {
  fmt.Println("pig: walk")
  }
  func main() {
  // 創建動物的名字到實例的映射
  animals := map[string]interface{}{
  "bird": new(bird),
  "pig": new(pig),
  }
  // 遍歷映射
  for name, obj := range animals {
  // 判斷對象是否為飛行動物
  f, isFlyer := obj.(Flyer)
  // 判斷對象是否為行走動物
  w, isWalker := obj.(Walker)
  fmt.Printf("name: %s isFlyer: %v isWalker: %v\n", name, isFlyer, isWalker)
  // 如果是飛行動物則調用飛行動物接口
  if isFlyer {
  f.Fly()
  }
  // 如果是行走動物則調用行走動物接口
  if isWalker {
  w.Walk()
  }
  }
  }
  代碼說明如下:
  第 6 行定義了飛行動物的接口。
  第 11 行定義了行走動物的接口。
  第 16 和 30 行分別定義了鳥和豬兩個對象,并分別實現了飛行動物和行走動物接口。
  第 41 行是一個 map,映射對象名字和對象實例,實例是鳥和豬。
  第 47 行開始遍歷 map,obj 為 interface{} 接口類型。
  第 50 行中,使用類型斷言獲得 f,類型為 Flyer 及 isFlyer 的斷言成功的判定。
  第 52 行中,使用類型斷言獲得 w,類型為 Walker 及 isWalker 的斷言成功的判定。
  第 57 和 62 行,根據飛行動物和行走動物兩者是否斷言成功,調用其接口。
  代碼輸出如下:
  name: pig isFlyer: false isWalker: true
  pig: walk
  name: bird isFlyer: true isWalker: true
  bird: fly
  bird: walk
  將接口轉換為其他類型
  在代碼 1 中,可以實現

將接口轉換為普通的指針類型。例如將 Walker 接口轉換為 *pig 類型,請參考下面的代碼:

  p1 := new(pig)var a Walker = p1p2 := a.(*pig)fmt.Printf("p1=%p p2=%p", p1, p2)

  對代碼的說明如下:

  第 3 行,由于 pig 實現了 Walker 接口,因此可以被隱式轉換為 Walker 接口類型保存于 a 中。

  第 4 行,由于 a 中保存的本來就是 *pig 本體,因此可以轉換為 *pig 類型。

  第 6 行,對比發現,p1 和 p2 指針是相同的。

  如果嘗試將上面這段代碼中的 Walker 類型的 a 轉換為 *bird 類型,將會發出運行時錯誤,請參考下面的代碼:

  p1 := new(pig)var a Walker = p1p2 := a.(*bird)

  運行時報錯:

  panic: interface conversion: main.Walker is *main.pig, not *main.bird

  報錯意思是:接口轉換時,main.Walker 接口的內部保存的是 *main.pig,而不是 *main.bird。

  因此,接口在轉換為其他類型時,接口內保存的實例對應的類型指針,必須是要轉換的對應的類型指針。

以上是“Go語言接口和類型如的轉換方法”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

go
AI

南昌县| 霍山县| 久治县| 河曲县| 慈利县| 揭西县| 康平县| 景泰县| 溧阳市| 盐亭县| 邢台县| 象州县| 喀什市| 泗洪县| 德钦县| 台州市| 聂荣县| 岳普湖县| 和龙市| 高要市| 晴隆县| 平陆县| 七台河市| 恩平市| 江永县| 海伦市| 凤台县| 绥芬河市| 兴城市| 东城区| 邛崃市| 保靖县| 辉南县| 富川| 平远县| 丰镇市| 吴堡县| 桐乡市| 南木林县| 紫金县| 武山县|