簡體   English   中英

去隱式轉換到接口做內存分配?

[英]Go implicit conversion to interface does memory allocation?

當使用類型為interface{}可變參數(例如Printf )定義函數時,參數顯然會隱式轉換為接口實例。

此轉換是否意味着內存分配? 轉換速度快嗎? 當關注代碼效率時,我應該避免使用可變參數函數嗎?

我發現關於Go中接口內存分配的最佳解釋仍然來自Rus Cox,這是Go的核心程序員之一。 值得一讀的是它。

http://research.swtch.com/interfaces

我找到了一些最有趣的部分:

存儲在接口中的值可能是任意大的,但只有一個字專用於將值保存在接口結構中,因此賦值在堆上分配一塊內存並將指針記錄在單字槽中。

...

調用fmt.Printf(),Go編譯器生成代碼,該代碼從itable調用適當的函數指針,將接口值的數據字作為函數的第一個(在此示例中,僅)參數傳遞。

Go的動態類型轉換意味着編譯器或鏈接器預先計算所有可能的itables是不合理的:有太多(接口類型,具體類型)對,並且大多數都不需要。 相反,編譯器為每個具體類型生成類型描述結構,如Binary或int或func(map [int] string)。 在其他元數據中,類型描述結構包含由該類型實現的方法的列表。

...

接口運行時通過查找具體類型的方法表中接口類型的方法表中列出的每個方法來計算itable。 運行時在生成它之后緩存itable,因此這種對應只需要計算一次。

...

如果涉及的接口類型為空 - 它沒有方法 - 那么除了將指針保持在原始類型之外,itable沒有用處。 在這種情況下,可以刪除itable,並且值可以直接指向類型。

因為Go具有靜態類型的提示以與動態方法查找一起使用,所以它可以將查找從調用站點移回到值存儲在接口中的點。

轉換為interface{}是與變量參數分開的概念,它包含在切片中,可以是任何類型。 但是,只要它們不會逃逸到堆中(在GC工具鏈中),這些都可能在分配意義上是免費的。

您將從fmt函數(如Printf中看到的多余分配將來自反射,而不是來自使用interface{}或可變參數。

如果您關注效率,那么避免間接將始終更有效,因此使用正確的值類型將產生更高效的代碼。 但差異可能很小,因此在對自己進行微小優化之前先對代碼進行基准測試。

Go傳遞參數copy_by_value,因此它無論如何都會進行內存分配。 如果可能的話,你總是應該更好地避免使用接口{}。 在描述的情況下,您的函數將需要反映使用它們的參數。 反射是相當昂貴的操作,這就是為什么fmt.Printf()如此緩慢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM