原文:http://research.swtch.com/generic
常用的資料結構(vectors,queues,maps,trees,等等)似乎是評估一個新語言的一個熱門話題。Go語言的FAQ中有一條就是關於Go中的泛型程式設計。對於泛型程式設計的通常有以下三種處理方式:
1.(C語言)放棄泛型。這樣苦了程式員,但是這樣沒前增加太多複雜的東西到語言中。
2.(C++語言)編譯期特化或者大量地展開代碼。這樣苦了編譯器。編繹器產生一堆代碼,而大部分是無用的,需要一個很好的連結器去清除重複的副本。為每一個類型產生一份代碼,也許這樣會讓代碼高效,但是程式是一個整體,這樣會造成對cpu的cache不友好。我曾聽說一個簡單的庫修正和移除了模板後,text段(即動態連結程式庫的檔案格式中的text段)的大小從M級降到10K。
3.(Java語言)隱式地把所有東西裝箱。這樣苦了程式,這樣執行起來會變慢。
對比C語言的手寫,C++語言的編譯器產生,Java代碼最簡單,但是最低效,無論是從時間還是空間來說。因為所有的操作都要隱式地裝箱和拆箱。一個byte的vector容器(Vector<Byte>)所佔的空間比遠超一個位元組每一個byte。想要隱藏裝箱和拆箱會讓類型系統變複雜。從另一個方面來說,這個也許是指令cache友好的,因為它把一個byte的vector(Vector<Byte>)可以分開來寫每一個byt e。
泛型程式設計的困境是:要麼苦了程式員,要麼苦了編繹器,要麼降低運行時效率。
=====================================================
原文作者是Go語言的實現者之一。
從Go的FAQ中也可以看到他們並不急於去實現泛型,是因為還沒有找到一個合適的實現方案去解決上面的困境。
因為Go目前沒有泛型,所以只能用interface來實現常用的資料結構了。但是從我個人角度來看Go中的interface的效率有點慢(比C++中的虛函數要慢,想想一個Vector容器,調用一個get函數,都比調用C++的一個虛函數還要慢。。)。
所以在Go1.0之前,有Vector容器時,另外還有一個IntVector和一個StringVector。想想有夠蛋疼的,如果我想用一個高效float的Vector,是不是還要寫一個FloatVector?
如果Go能支援泛型,那真是相當令人高興的一件事。