成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我終于識破了這個 Go 編譯器把戲

開發 后端
在 Go 語言的日常編碼工作中,有一個非常普遍但詭異的編譯錯誤,曾讓我十分困惑。這個問題我相信不少 Gopher 都遇到過,不妨來看一下。

[[421872]]

本文轉載自微信公眾號「Golang技術分享」,作者機器鈴砍菜刀。轉載本文請聯系Golang技術分享公眾號。

在 Go 語言的日常編碼工作中,有一個非常普遍但詭異的編譯錯誤,曾讓我十分困惑。這個問題我相信不少 Gopher 都遇到過,不妨來看一下。

背景回顧

我們定義一個帶有 WriteGoCode() 方法的 Gopher 接口,同時定義了 person 結構體,它存在 WriteGoCode() 方法。

  1. type Gopher interface { 
  2.  WriteGoCode() 
  3.  
  4. type person struct { 
  5.  name string 
  6.  
  7. func (p person) WriteGoCode() { 
  8.  fmt.Printf("I am %s, i am writing go code!\n", p.name

在 Go 語言中,只要某對象擁有接口的所有方法,那該對象即實現了該接口。p 是 person 結構體的實例化對象, Coding() 函數的入參是 Gopher 接口, person 對象實現了 Gopher 接口,因此 p 入參成功被運行。

  1. func Coding(g Gopher) { 
  2.  g.WriteGoCode() 
  3.  
  4. func main() { 
  5.  p := person{name"小菜刀"
  6.  Coding(p) 
  7.  
  8. // output
  9. I am 小菜刀, i am writing go code! 

此時,我們將 Coding() 函數的入參改為 []Gopher 類型,入參為 []person 。

  1. func Coding(g Gopher) { 
  2.  g.WriteGoCode() 
  3.  
  4. func main() { 
  5.  p := person{name"小菜刀"
  6.  Coding(p) 
  7.  
  8. // output
  9. I am 小菜刀, i am writing go code! 

但是,這個時候,編譯卻不能通過!

  1. ./main.go:29:8: cannot use p (type []person) as type []Gopher in argument to Coding 

明明 person 類型實現了 Gopher 接口,且當函數入參為 Gopher 類型時,能夠順利被執行,但參數變為 []Gopher 時,卻過不了編譯,這是為什么?

語法通用規則

這個問題在 stackoverflow 上被熱議,詳情見文末參考鏈接1。

在 Go 中,有一個通用規則,即語法不應隱藏復雜/昂貴的操作。轉換一個 string 到 interface{} 它的時間復雜度是 O(1),轉換 []string 到 interface{} 同樣也是一個 O(1) 操作,因為它還是一個單一值的轉換。

如果要將 []string 轉換為 []interface{},它是 O(N) 操作。因為切片的每個元素都必須轉換為 interface{},這違背了 Go 的語法原則。

這個回答,你們同意嗎?

當然,此規則存在一個例外:轉換字符串。在將 string 轉換為 []byte 或 []rune 時,即使需要 O(n) 操作,但 Go 會允許執行。

InterfaceSlice 問題

Ian Lance Taylor(Go 核心開發者) 在 Go 官方倉庫中也回答了這個問題,詳情見文末參考鏈接2。他給出了這樣做的兩個主要原因。

原因一:類型為 []interface{} 的變量不是 interface!它僅僅是一個元素類型恰好為 interface{} 的切片。

原因二:[]interface{} 變量有特定大小的內存布局,在編譯期可知。這與 []MyType 是不同的。

每個 interface{} (運行時通過 runtime.eface 表示)占兩個字長(一個字代表所包含內容的類型 _type,另外一個字表示所包含的數據 data 或者指向它的指針 )

因此,類型為 []interface{} 的長度為 N 的變量,它是由 N*2 個字長的數據塊支持。而這與類型為 []MyType 的長度為 N 的變量的數據塊大小是不同的,因為后者的數據塊是 N*sizeof(MyType) 字長。

數據塊的不同,造成的結果是編譯器無法快速地將 []MyType 類型的內容分配給 []interface{} 類型的內容。

同理,[]Gopher 變量也是特定大小的內存布局(運行時通過 runtime.iface 表示)。這同樣不能快速地將 []MyType 類型的內容分配給 []Gopher 類型。

因此,Ian Lance Taylor 回答閉環了 Go 的語法通用規則:Go 語法不應隱藏復雜/昂貴的操作,編譯器會拒絕它們。

代碼解決方案

再次將文章開頭的例子附上,如果我們需要 [] person 類型的 p 能夠成功入參 Coding() 函數,應該如何做呢。

  1. func Coding(gs []Gopher) { 
  2.  for _, g := range gs { 
  3.   g.WriteGoCode() 
  4.  } 
  5.  
  6. func main() { 
  7.  p := []person{ 
  8.   {name"小菜刀1號"}, 
  9.   {name"小菜刀2號"}, 
  10.  } 
  11.  Coding(p) 

代碼方案如下,核心是需要一個 []Gopher 類型的轉換變量。

  1. func main() { 
  2.  p := []person{ 
  3.   {name"小菜刀1號"}, 
  4.   {name"小菜刀2號"}, 
  5.  } 
  6.  var interfaceSlice []Gopher = make([]Gopher, len(p)) 
  7.  for i, g := range p { 
  8.   interfaceSlice[i] = g 
  9.  } 
  10.  Coding(interfaceSlice) 
  11.  
  12. // output
  13. I am 小菜刀1號, i am writing go code! 
  14. I am 小菜刀2號, i am writing go code! 

總結

由于 []MyType 到 []interface{} 的轉換,是昂貴的操作,Go 編譯器不會允許這種情況通過編譯,故而將這種開銷的責任傳遞給開發者。

Go 是一門編譯速度很快的語言,得益于它語法設計中貫徹著 “simpler is better” 的理念,這可不是說說而已。

參考鏈接

【1. Type converting slices of interfaces】https://stackoverflow.com/questions/12753805/type-converting-slices-of-interfaces/12754757#12754757

【2. InterfaceSlice】https://github.com/golang/go/wiki/InterfaceSlice

 

責任編輯:武曉燕 來源: Golang技術分享
相關推薦

2013-12-30 11:21:31

Go編譯器

2022-07-01 06:44:42

微信應用偽裝應用轉生

2022-08-22 07:38:01

Go語言函數

2021-08-22 17:18:58

Go代碼泛型代碼

2010-01-18 10:34:21

C++編譯器

2010-01-21 09:11:38

C++編譯器

2009-08-10 17:12:54

C#編譯器

2017-03-20 18:01:55

編譯器匯編

2013-03-29 10:02:37

編譯器語言編譯開發

2010-03-23 11:17:16

Python 動態編譯

2021-05-13 18:53:34

Go編譯器Uber

2010-10-20 13:43:37

C++編譯器

2019-08-06 08:20:07

編譯器工具開發者

2020-11-10 13:42:07

Go編譯器修復

2010-02-02 17:08:26

Python靜態編譯器

2010-02-02 17:08:26

Python靜態編譯器

2010-03-02 10:55:47

Linux SkyEy

2011-05-18 11:06:25

java編譯器

2010-09-16 15:57:25

Java編譯器

2009-08-06 14:59:36

C#編譯器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产av毛片 | 91精品国产91久久久久久最新 | 精品国产乱码久久久久久牛牛 | 国产成人综合网 | 久久精品小短片 | 日韩在线成人 | 视频一区在线观看 | 久草欧美视频 | 天堂一区在线 | 国产羞羞视频在线观看 | 亚洲a在线观看 | 桃花av在线| 国产精品久久久久久久久久久免费看 | 97伦理最新伦理 | 欧美一区二区三区的 | 亚洲综合色网站 | 福利二区 | 影音先锋欧美资源 | 毛片网站在线观看 | 婷婷久久精品一区二区 | 影音先锋中文字幕在线观看 | 欧美又大粗又爽又黄大片视频 | 四虎影院新网址 | 亚洲不卡视频 | 国产精品免费一区二区三区 | 国产精品久久久久久久岛一牛影视 | 日本又色又爽又黄又高潮 | 日韩av手机在线观看 | 久久精品99国产精品 | 九九热免费在线观看 | 久久久性| 九九久久久 | 久久爆操 | 欧美日韩一区精品 | 亚洲一区二区久久久 | 91久久久久久久久久久久久 | 久久久久国产精品一区 | 国产午夜亚洲精品不卡 | 亚洲欧美综合精品久久成人 | 偷拍自拍第一页 | 亚洲 欧美 激情 另类 校园 |