国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

讓我一起談談Go中接口

開發(fā) 后端
接口類型的變量可以保存實現(xiàn)接口的類型的值。該類型的值成為接口的動態(tài)值,并且該類型成為接口的動態(tài)類型。

 [[408979]]

本文轉載自微信公眾號「光城」,作者lightcity。轉載本文請聯(lián)系光城公眾號。

1.接口

在Go中使用interface關鍵字聲明一個接口:

  1. type Shaper interface { 
  2.  Area() float64 
  3.  Perimeter() float64 

如果我們直接使用fmt庫進行輸出,會得到什么結果呢?

  1. func main() { 
  2.  var s Shaper 
  3.  fmt.Println("value of s is ", s) 
  4.  fmt.Printf("type of s is %T\n", s) 

輸出:

  1. value of s is  <nil> 
  2. type of s is <nil> 

在這里,引出接口的概念。接口有兩種類型。接口的靜態(tài)類型是接口本身,例如上述程序中的Shape。接口沒有靜態(tài)值,而是指向動態(tài)值。

接口類型的變量可以保存實現(xiàn)接口的類型的值。該類型的值成為接口的動態(tài)值,并且該類型成為接口的動態(tài)類型。

從上面的示例開始,我們可以看到零值和接口的類型為nil。這是因為,此刻,我們已聲明類型Shaper的變量s,但未分配任何值。當我們使用帶有接口參數(shù)的fmt包中的Println函數(shù)時,它指向接口的動態(tài)值,Printf功能中的%T語法是指動態(tài)類型的接口。實際上,接口靜態(tài)類型是Shaper。

當我們使用一個類型去實現(xiàn)該接口后,會是什么效果。

  1. type Rect struct { 
  2.  width  float64 
  3.  height float64 
  4.  
  5. func (r Rect) Area() float64 { 
  6.  return r.width * r.height 
  7.  
  8. func (r Rect) Perimeter() float64 { 
  9.  return 2 * (r.width + r.height) 
  10.  
  11. // main 
  12. func main() { 
  13.  var s Shaper 
  14.  fmt.Println("value of s is ", s) 
  15.  fmt.Printf("type of s is %T\n", s) 
  16.  s = Rect{5.0, 4.0} 
  17.  r := Rect{5.0, 4.0} 
  18.  fmt.Printf("type of s is %T\n", s) 
  19.  fmt.Printf("value of s is %v\n", s) 
  20.  fmt.Printf("area of rect is %v\n", s.Area()) 
  21.  fmt.Println("s == r is", s == r) 

輸出:

  1. value of s is  <nil> 
  2. type of s is <nil> 
  3. type of s is main.Rect 
  4. value of s is {5 4} 
  5. area of rect is 20 
  6. s == r is tru 

可以看到此時s變成了動態(tài)類型,存儲的是main.Rect,值變成了{5,4}。

有時,動態(tài)類型的接口也稱為具體類型,因為當我們訪問接口類型時,它會返回其底層動態(tài)值的類型,并且其靜態(tài)類型保持隱藏。

我們可以在s上調用Area方法,因為接口Shaper定義了Area方法,而s的具體類型是Rect,它實現(xiàn)了Area方法。該方法將在接口保存的動態(tài)值上被調用。

此外,我們可以看到我們可以使用s與r進行比較,因為這兩個變量都保存相同的動態(tài)類型(Rect類型的結構)和動態(tài)值{5 4}。

我們接著使用圓來實現(xiàn)該接口:

  1. type Circle struct { 
  2.  radius float64 
  3.  
  4. func (c Circle) Area() float64 { 
  5.  return 3.14 * c.radius * c.radius 
  6.  
  7. func (c Circle) Perimeter() float64 { 
  8.  return 2 * 3.14 * c.radius 
  9. // main 
  10. s = Circle{10} 
  11. fmt.Printf("type of s is %T\n", s) 
  12. fmt.Printf("value of s is %v\n", s) 
  13. fmt.Printf("area of rect is %v\n", s.Area()) 

此時輸出:

  1. type of s is main.Circle 
  2. value of s is {10} 
  3. area of rect is 314 

這里進一步理解了接口保存的動態(tài)類型。從切片角度出發(fā),可以說,接口也以類似的方式工作,即動態(tài)保存對底層類型的引用。

當我們刪除掉Perimeter的實現(xiàn),可以看到如下報錯結果。

  1. ./rect.go:34:4: cannot use Rect{...} (type Rect) as type Shaper in assignment: 
  2. Rect does not implement Shaper (missing Perimeter method) 

從上面的錯誤應該是顯而易見的,為了成功實現(xiàn)接口,需要實現(xiàn)與完全簽名的接口聲明的所有方法。

2.空接口

當一個接口沒有任何方法時,它被稱為空接口。這由接口{}表示。因為空接口沒有方法,所以所有類型都隱式地實現(xiàn)了這個接口。

空接口的作用之一在于:函數(shù)可以接收多個不同類型參數(shù)。

例如:fmt的Println函數(shù)。

  1. func Println(a ...interface{}) (n int, err error) 

Println是一個可變函數(shù),它接受interface{}類型的參數(shù)。

例如:

  1. type MyString string 
  2.  
  3. func explain(i interface{}) { 
  4.  fmt.Printf("type: %T, value: %v\n", i, i) 
  5. // main 
  6. s := MyString("hello"
  7. explain(s) 
  8. r := Rect{1, 2} 
  9. explain(r) 

輸出:

  1. type: inter.MyString, value: hello 
  2. type: inter.Rect, value: {1 2} 

可以看到空接口的類型與值是動態(tài)的。

3.多個接口

在下面的程序中,我們用Area方法創(chuàng)建了Shape接口,用Volume方法創(chuàng)建了Object接口。因為結構類型Cube實現(xiàn)了這兩個方法,所以它實現(xiàn)了這兩個接口。因此,我們可以將結構類型Cube的值賦給類型為Shape或Object的變量。

  1. type IShape interface { 
  2.  Area() float64 
  3.  
  4. type Object interface { 
  5.  Volume() float64 
  6.  
  7. type Cube struct { 
  8.  side float64 
  9.  
  10. func (c Cube) Area() float64 { 
  11.  return 6 * c.side * c.side 
  12.  
  13. func (c Cube) Volume() float64 { 
  14.  return c.side * c.side * c.side 
  15. // main 
  16. c := Cube{3} 
  17. var s IShape = c 
  18. var o Object = c 
  19. fmt.Println("area is", s.Area()) 
  20. fmt.Println("Volume is", o.Volume()) 

這種調用是沒有問題的,調用各自動態(tài)類型的方法。

那如果是這樣呢?

  1. fmt.Println("area of s of interface type IShape is", s.Volume()) 
  2. fmt.Println("volume of o of interface type Object is", o.Area()) 

輸出:

  1. s.Volume undefined (type Shape has no field or method Volume) 
  2. o.Area undefined (type Object has no field or method Area) 

這個程序無法編譯,因為s的靜態(tài)類型是IShape,而o的靜態(tài)類型是Object。因為IShape沒有定義Volume方法,Object也沒有定義Area方法,所以我們得到了上面的錯誤。

要使其工作,我們需要以某種方式提取這些接口的動態(tài)值,這是一個立方體類型的結構體,立方體實現(xiàn)了這些方法。這可以使用類型斷言來完成。

4.類型斷言

我們可以通過i.(Type)確定接口i的底層動態(tài)值,Go將檢查i的動態(tài)類型是否與type相同,并返回可能的動態(tài)值。

  1. var s1 IShape = Cube{3} 
  2. c1 := s1.(Cube
  3. fmt.Println("area of s of interface type IShape is", c1.Volume()) 
  4. fmt.Println("volume of o of interface type Object is", c1.Area()) 

這樣便可以正常工作了。

如果IShape沒有存儲Cube類型,且Cube沒有實現(xiàn)IShape,那么報錯:

  1. impossible type assertion: 
  2. Cube does not implement IShape (missing Area method) 

如果IShape沒有存儲Cube類型,且Cube實現(xiàn)Shape,那么報錯:

  1. panic: interface conversion: inter.IShape is nil, not inter.Cub 

幸運的是,語法中還有另一個返回值:

  1. value, ok := i.(Type) 

在上面的語法中,如果i有具體的type類型或type的動態(tài)值,我們可以使用ok變量來檢查。如果不是,那么ok將為假,value將為Type的零值(nil)。

此外,使用類型斷言可以檢查該接口的動態(tài)類型是否實現(xiàn)了其他接口,就像前面的IShape的動態(tài)類型是Cube,它實現(xiàn)了IShape、Object接口,如下例子:

  1. vaule1, ok1 := s1.(Object) 
  2. value2, ok2 := s1.(Skin) 
  3. fmt.Printf("IShape s的動態(tài)類型值是: %v, 該動態(tài)類型是否實現(xiàn)了Object接口: %v\n", vaule1, ok1) 
  4. fmt.Printf("IShape s的動態(tài)類型值是: %v, 該動態(tài)類型是否實現(xiàn)了Skin接口: %v\n", value2, ok2) 

輸出:

  1. IShape s的動態(tài)類型值是: {3}, 該動態(tài)類型是否實現(xiàn)了Object接口: true 
  2. IShape s的動態(tài)類型值是: <nil>, 該動態(tài)類型是否實現(xiàn)了Skin接口: false 

類型斷言不僅用于檢查接口是否具有某個給定類型的具體值,而且還用于將接口類型的給定變量轉換為不同的接口類型。

5.類型Switch

在前面的空接口中,我們知道將一個空接口作為函數(shù)參數(shù),那么該函數(shù)可以接受任意類型,那如果我有一個需求是:當傳遞的數(shù)據(jù)類型是字符串時,要求全部變?yōu)榇髮懀渌愋筒贿M行操作?

針對這樣的需求,我們可以采用Type Switch,即:i.(type)+switch。

  1. func switchProcess(i interface{}) { 
  2.  switch i.(type) { 
  3.  case string: 
  4.   fmt.Println("process string"
  5.  case int
  6.   fmt.Println("process int"
  7.  default
  8.   fmt.Printf("type is %T\n", i) 
  9.  } 

輸出:

  1. process int 
  2. process string 

6.嵌入接口

在Go中,一個接口不能實現(xiàn)或擴展其他接口,但我們可以通過合并兩個或多個接口來創(chuàng)建一個新的接口。

例如:

這里使用Runner與Eater兩個接口,組合成了一個新接口RunEater,該接口為Embedding interfaces。

  1. type Runner interface { 
  2.  run() string 
  3. type Eater interface { 
  4.  eat() string 
  5.  
  6. type RunEater interface { 
  7.  Runner 
  8.  Eater 
  9.  
  10. type Dog struct { 
  11.  age int 
  12.  
  13. func (d Dog) run() string { 
  14.  return "run" 
  15.  
  16. func (d Dog) eat() string { 
  17.  return "eat" 
  18.  
  19. // main 
  20. d := Dog{10} 
  21. var re RunEater = d 
  22. var r Runner = d 
  23. var e Eater = d 
  24. fmt.Printf("RunnEater dynamic type: %T, value: %v\n", re, re) 
  25. fmt.Printf("Runn dynamic type: %T, value: %v\n", r, r) 
  26. fmt.Printf("Eater dynamic type: %T, value: %v\n", e, e) 

輸出:

  1. RunnEater dynamic type: inter.Dog, value: {10} 
  2. Runn dynamic type: inter.Dog, value: {10} 
  3. Eater dynamic type: inter.Dog, value: {10} 

7.接口比較

如果基礎動態(tài)值為nil,則兩個接口總是相等的,這意味著兩個nil接口總是相等的,因此== operation返回true。

  1. var a, b interface{} 
  2. fmt.Println( a == b ) // true 

如果這些接口不是nil,那么它們的動態(tài)類型(具體值的類型)應該相同,具體值應該相等。

如果接口的動態(tài)類型不具有可比性,例如slice、map、function,或者接口的具體值是包含這些不可比較性值的復雜數(shù)據(jù)結構,如切片或數(shù)組,則==或!=操作將導致運行時panic。

學習自https://medium.com/rungo/interfaces-in-go-ab1601159b3a

 

責任編輯:武曉燕 來源: 光城
相關推薦

2021-04-12 18:03:39

Nginx架構負載

2021-09-11 19:02:34

Hook使用版本

2021-01-12 05:08:49

DHCP協(xié)議模型

2021-12-16 12:01:21

區(qū)塊鏈Libra貨幣

2022-11-02 08:41:40

2023-03-26 23:47:32

Go內存模型

2024-02-26 00:00:00

Go性能工具

2022-07-10 23:15:46

Go語言內存

2009-06-19 15:11:34

DWR和Spring

2021-09-14 17:16:21

Java 同步工具類

2021-07-12 11:35:13

Go協(xié)程Goroutine

2024-11-27 08:47:12

2025-05-26 03:15:00

接口高可用框架

2023-11-29 09:04:00

前端接口

2015-10-20 16:48:06

AnsibleDocker可擴展設計

2022-12-02 14:20:09

Tetris鴻蒙

2022-11-29 16:35:02

Tetris鴻蒙

2024-05-17 08:47:33

數(shù)組切片元素

2024-06-27 08:54:22

Go模塊團隊

2022-02-22 10:50:19

IDEAGit工具,
點贊
收藏

51CTO技術棧公眾號

成人信息集中地欧美| 亚洲中国最大av网站| 欧美激情一区二区久久久| www在线免费观看视频| 中文字幕亚洲在| 国产1区2区在线| www.亚洲色图.com| 天天想你在线观看完整版电影免费| 欧美精品一区二区三区三州| 色喇叭免费久久综合网| 91精品国产91久久久久福利| 嘿咻视频在线看| 国产一区二区成人久久免费影院| 亚洲1区2区3区视频| 欧美日韩在线精品| 成人av影视| 中文字幕国产一区| 黄色一级大片在线观看| av福利精品导航| 欧美日韩亚洲国产成人| 精品一区二区三区在线观看国产 | 午夜日本精品| 国产精品日韩一区二区免费视频| 中文字幕一区二区三区在线视频| 成人午夜黄色影院| 精品1区2区3区4区| 久久亚洲午夜电影| 日本色综合中文字幕| 免费电影一区| 国产一区视频网站| 成人久久久久久久久| 亚洲国产精品v| 日本高清不卡中文字幕| 亚洲va韩国va欧美va| 色大18成网站www在线观看| 日韩视频一区在线观看| 不卡一二三区| 欧美激情一级精品国产| 日韩av片子| 久久亚洲免费| 不卡一二三区首页| 欧美艹逼视频| 91精品在线观看入口| 深夜视频一区二区| 午夜精品久久久久久久久久久久久| 蜜臀91精品国产高清在线观看| 国产精品亚洲自拍| 日韩激情一区二区| 欧洲av无码放荡人妇网站| 亚洲国产精品综合小说图片区| 91成人高清| 日韩视频免费观看| 国产精品不卡| eeuss中文| 亚洲人成网站色在线观看| 中文av在线播放| 欧美一级欧美一级在线播放| 中文在线最新版地址| 欧美亚洲伦理www| 国产精品www994| 人人妻人人做人人爽| 亚洲18女电影在线观看| sm捆绑调教国产免费网站在线观看 | 97超级碰碰| 日韩av网站免费在线| 91视频免费版污| 欧美日韩国产首页在线观看| 少妇高潮一区二区三区99| 91久久精品一区二区别| 成人精品一区二区三区中文字幕| 成片免费观看视频| 亚洲成人黄色网| 亚洲动漫精品| 一区二区三区视频| 一区二区三区免费在线观看| a√中文在线观看| 国产精品视频导航| 国产东北露脸精品视频| 日本亚洲欧美| 欧美丰满老妇厨房牲生活 | 9久草视频在线视频精品| 中午字幕在线观看| 在线亚洲午夜片av大片| 欧美精品首页| 国产精品区在线| 日韩电影中文字幕| 午夜久久久久| caoporn97免费视频公开| 亚洲二区在线播放视频| 91精品久久久久久久蜜月| 无罩大乳的熟妇正在播放| 在线观看欧美精品| 色狠狠久久av综合| 日韩精品一区二区三区四| 欧美日韩亚洲综合在线| 欧美一区二区三区红桃小说| 日韩精品在线观看av| 欧美一区二区三区视频在线| 精品少妇av| 在线观看的毛片| 伊人久久精品视频| 玖玖国产精品视频| 日本一本草久在线中文| 国产成人av网| 日本一区二区动态图| 91精品美女| 亚洲黄色网址在线观看| 欧美酷刑日本凌虐凌虐| 一区二区免费不卡在线| 天堂在线视频中文网| 久久久久久12| 91免费看片在线观看| 成人天堂yy6080亚洲高清| 久久婷婷开心| 欧美视频一区二区在线观看| 在线观看一区二区三区三州| 色婷婷亚洲婷婷| 欧美精品一区二区久久| 人人干人人干人人| 欧美大胆在线视频| 国产一区二区在线看| 久久亚洲导航| 热re99久久精品国99热蜜月| 欧美猛男男办公室激情| 99成人免费视频| 午夜伦理在线| 欧美日韩三区四区| 91精品国产综合久久福利软件| 黑人一区二区三区四区五区| 麻豆影视在线| 国内精品一区二区| 欧美片网站yy| 久久亚洲色图| 成人免费高清观看| 久久av秘一区二区三区| 亚洲人永久免费| 国产91对白在线观看九色| 在线女人免费视频| 大地资源第二页在线观看高清版| 亚洲精品电影网站| 国产成人在线影院| 五月天色综合| 一级黄色特级片| 国产精品久久久久久久9999| 亚洲高清不卡在线| 91av精品| 菠萝菠萝蜜在线观看| 一区二区三区在线视频111| 精品亚洲夜色av98在线观看| 成人一区二区三区在线观看| 久久伊人精品| 最新理论片影院| 国产一区二区三区四区hd| 精品美女在线观看| 成人午夜视频在线| 日韩高清在线免费观看| 久草在线免费福利资源| 五月天色一区| 一区二区三区动漫| 中文字幕在线免费不卡| 国产精品久久久久一区二区三区厕所 | 成人做爰高清视频网站| 成人美女免费网站视频| 91精品国产入口| 国产成人精品免费| 国产精品午夜av| 青青国产在线| 亚洲人久久久| 国内精品视频一区| 欧美三级三级三级爽爽爽| 激情文学综合插| y111111国产精品久久久| 欧美美女色图| 香港三级日本三级a视频| 日韩免费视频在线观看| 日韩一级大片在线观看| 国产69精品久久99不卡| 青草国产精品| 校园春色亚洲| 久草免费在线播放| 欧美大香线蕉线伊人久久| www.欧美免费| 欧美曰成人黄网| eeuss影院一区二区三区| 欧美一级精品| 成人影院入口| 久草热久草在线频| 国产激情片在线观看| 91精品久久久久久久久久入口 | 国产成+人+综合+亚洲欧洲| 欧美精品日韩综合在线| 91一区一区三区| 亚洲国产日韩欧美一区二区三区| 国内欧美日韩| 在线观看免费版| 91av俱乐部| 亚洲无玛一区| 亚洲xxxx视频| 欧美一级片在线播放| 亚洲女同性videos|