Go 由于不支持泛型而臭名昭著,但最近,泛型已接近成為現實。Go 團隊實施了一個看起來比較穩定的設計草案,并且正以源到源翻譯器原型的形式獲得關注。本文講述的是泛型的最新設計,以及如何自己嘗試泛型。

專注于為中小企業提供做網站、網站建設服務,電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業桐梓免費做網站提供優質的服務。我們立足成都,凝聚了一批互聯網行業人才,有力地推動了近1000家企業的穩健成長,幫助中小企業通過網站建設實現規模擴充和轉變。
例子
FIFO Stack
假設你要創建一個先進先出堆棧。沒有泛型,你可能會這樣實現:
type?Stack?[]interface{}func?(s?Stack)?Peek()?interface{}?{
return?s[len(s)-1]
}
func?(s?*Stack)?Pop()?{
*s?=?(*s)[:
len(*s)-1]
}
func?(s?*Stack)?Push(value?interface{})?{
*s?=?
append(*s,?value)
}
但是,這里存在一個問題:每當你 Peek 項時,都必須使用類型斷言將其從 interface{} 轉換為你需要的類型。如果你的堆棧是 *MyObject 的堆棧,則意味著很多 s.Peek().(*MyObject)這樣的代碼。這不僅讓人眼花繚亂,而且還可能引發錯誤。比如忘記 * 怎么辦?或者如果您輸入錯誤的類型怎么辦?s.Push(MyObject{})` 可以順利編譯,而且你可能不會發現到自己的錯誤,直到它影響到你的整個服務為止。
通常,使用 interface{} 是相對危險的。使用更多受限制的類型總是更安全,因為可以在編譯時而不是運行時發現問題。
泛型通過允許類型具有類型參數來解決此問題:
type?Stack(type?T)?[]Tfunc?(s?Stack(T))?Peek()?T?{
return?s[len(s)-1]
}
func?(s?*Stack(T))?Pop()?{
*s?=?(*s)[:
len(*s)-1]
}
func?(s?*Stack(T))?Push(value?T)?{
*s?=?
append(*s,?value)
}
這會向 Stack 添加一個類型參數,從而完全不需要 interface{}。現在,當你使用 Peek() 時,返回的值已經是原始類型,并且沒有機會返回錯誤的值類型。這種方式更安全,更容易使用。(譯注:就是看起來更丑陋,^-^)
此外,泛型代碼通常更易于編譯器優化,從而獲得更好的性能(以二進制大小為代價)。如果我們對上面的非泛型代碼和泛型代碼進行基準測試,我們可以看到區別:
type?MyObject?struct?{
X?
int
}
var?sink?MyObjectfunc?BenchmarkGo1(b?*testing.B)?{
for?i?:=?0;?i??b.N;?i++?{
var?s?Stack
s.Push(MyObject{})
s.Push(MyObject{})
s.Pop()
sink?=?s.Peek().(MyObject)
}
}
func?BenchmarkGo2(b?*testing.B)?{
for?i?:=?0;?i??b.N;?i++?{
var?s?Stack(MyObject)
s.Push(MyObject{})
s.Push(MyObject{})
s.Pop()
sink?=?s.Peek()
}
}
結果:
BenchmarkGo1BenchmarkGo1-16?????12837528?????????87.0?ns/op???????48?B/op????????2?allocs/opBenchmarkGo2BenchmarkGo2-16?????28406479?????????41.9?ns/op???????24?B/op????????2?allocs/op
在這種情況下,我們分配更少的內存,同時泛型的速度是非泛型的兩倍。
合約(Contracts)
上面的堆棧示例適用于任何類型。但是,在許多情況下,你需要編寫僅適用于具有某些特征的類型的代碼。例如,你可能希望堆棧要求類型實現 String() 函數
類型 在變量名后邊
也可不顯式聲明類型, 類型推斷, 但是是靜態語言, name一開始放字符串就不能再賦值數字
方法,屬性 分開 方法名首字母大寫就是就是外部可調的
面向對象設計的一個重要原則:“優先使用組合而不是繼承”
Dog 也是Animal , 要復用Animal 的屬性和方法,
只需要在結構體 type 里面寫 Animal
入口也是main, 用用試試
多態, 有這個方法就是這個接口的實現, 具體的類 不需要知道自己實現了什么接口,
使用: 在一個函數調用之前加上關鍵字go 就啟動了一個goroutine
創建一個goroutine,它會被加入到一個全局的運行隊列當中,
調度器 會把他們分配給某個 邏輯處理器 的隊列,
一個邏輯處理器 綁定到一個 操作系統線程 ,在上面運行goroutine,
如果goroutine需要讀寫文件, 阻塞 ,就脫離邏輯處理器 直接 goroutine - 系統線程 綁定
編譯成同名.exe 來執行, 不通過虛擬機, 直接是機器碼, 和C 一樣, 所以非常快
但是也有自動垃圾回收,每個exe文件當中已經包含了一個類似于虛擬機的runtime,進行goroutine的調度
默認是靜態鏈接的,那個exe會把運行時所需要的所有東西都加進去,這樣就可以把exe復制到任何地方去運行了, 因此 生成的 .exe 文件非常大
go語言沒有面向對象的特性,也沒有類對象的概念。但是,可以使用結構體來模擬這些特性,我們都知道面向對象里面有類方法等概念。我們也可以聲明一些方法,屬于某個結構體。
Go中的方法,是一種特殊的函數,定義域struct之上(與struct關聯、綁定),被稱為struct的接受者(receiver)。通俗的講,方法就是有接收者的函數。
語法格式如下:
mytype:定義一個結構體
recv:接受該方法的結構體(receiver)
my_method:方法名稱
para:參數列表
return_type:返回值類型
從語法格式可以看出,一個方法和一個函數非常相似,多了一個接受類型。
實例
運行結果
計算機編程語言,尤其是面向對象的編程語言,雖然語法不同,但其原理大都是相通的!那么go語言的method方法的繼承是否也有像python一樣的順序繼承的機制呢?我們來用一個簡單的實例探討一下。
因此,結論是go語言結構體(類)的繼承并沒有像python那樣的順序機制。
go語言method方法的繼承、重寫,繼承順序的探討 - 大器編程
新聞名稱:go語言面向對象實驗結論 go語言面向對象編程
本文來源:http://www.yijiale78.com/article22/ddgchjc.html
成都網站建設公司_創新互聯,為您提供網站維護、品牌網站制作、自適應網站、品牌網站建設、網站建設、移動網站建設
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯