[golang]讓golang支持泛型編程的一種方案

本博客原創博文版權所有 @[email protected]
僅供交流學習使用用於商業用途請聯繫原作者 
轉載請註明出處:http://blog.sina.com.cn/ally2014

總所周知,golang現在不支持泛型編程,對於習慣了C++泛型編程思想的程序員來說無疑是一個硬傷。
雖然golang interface{}多少可以滿足一些泛型需求,但是無論在效率和編程手法上,都無法達到C++template那樣的靈活性。出於對編譯器效率的考慮,官方暫時還沒有golang支持泛型的方案。
根據C++泛型的基本思路,我實現了一個名爲gpg[1]的工具,使用工具通過文字替換的方式生成需要的.go代碼,解決維護多個相似代碼的尷尬,通過配置.gpg(ini)實例化模板文件(.gp),替換相關模板參數
達到維護一份代碼(.gp),實現類型無關的編程思想。

如源碼中example所示,假如需要實現一個未知類型的全局變量,需要在get和set的時候自動加鎖,解決不同goroutine訪問全局變量時的衝突。按照現有go規則,使用interface{}每次進行類型斷言是一個辦法,但是應用起來代碼不好看,執行效率也沒有原生類型快。
還有一個辦法是用到什麼類型,就把已經實現的代碼拷貝一份改一改類型,這樣一旦算法有修改,需要修改所有的實現代碼,很不靠譜。
gpg可以解決以上所有問題. gpg的使用方法如下:
gpg tool 使用方法:
gpg-h    顯示幫助
gpg       遍歷當前目錄所有.gpg文件 用同名的.gp文件作爲模板生成.go代碼文件
gpg 遍歷path目錄所有.gpg文件 用同名的.gp文件作爲模板生成.go代碼文件
//////////////////////////////////////////example.gp
//This is an example of using gpg tool forgeneric-programming
//this is an example of using gpg to define an auto-lock globalvalue with generic type
//it will be realized to real go code by gpg tool through the .gpgfile with the same name
package example
import (
 "sync"
)
//auto locked global value
type AutoLockGbl struct {
 val 
 lock sync.RWMutex
}
//new and init a global value
func New(val ) *AutoLockGbl{
 p := &AutoLockGbl{}
 p.val = val
 return p
}
//get value, if modify is disable, lock is unneeded
func (me *AutoLockGbl) Get() (r ) {
 me.lock.RLock()
 defer me.lock.RUnlock()
 r = me.val
 return
}
//set value, if modify is disable, delete this function
func (me *AutoLockGbl) Set(val ) (r ) {
 me.lock.Lock()
 defer me.lock.Unlock()
 r = me.val
 me.val = val
 return
}

//////////////////////////////////////////example.gpg
//分別用int,string,uint64實例化example.gp
;this is exactlly an ini file
;it is used to generate code from .gp file
[int]
TYPE_NAME=Int
VALUE_TYPE=int
LOCK_COMMENT=
 
;禁止修改,不需要鎖
[const_str]
TYPE_NAME=ConstStr
VALUE_TYPE=string
LOCK_COMMENT=//
 
;禁止修改,不需要鎖
[const_u64]
TYPE_NAME=ConstU64
VALUE_TYPE=uint64
LOCK_COMMENT=//

可以得到形如以下的代碼文件
/////////////////////////////////example_gpg_int.go
// This file was auto-generated by [gpg] tool
// Last modify at: 2014-01-21 13:06:46.6378366 +0800 +0800
// !!!!!!!!!NEVER MODIFY IT MANUALLY!!!!!!!!!
//Copyright @Ally 2014. All rights reserved.
//Version:   1.0.0
//Author:   [email protected]
//Blog site: http://blog.sina.com.cn/ally2014
//This is an example of using gpg tool forgeneric-programming
//this is an example of using gpg to define an auto-lock globalvalue with generic type
//it will be realized to real go code by gpg tool through the .gpgfile with the same name
package example
import (
 "sync"
)
//auto locked global value
type AutoLockGblInt struct {
 val  int
 lock sync.RWMutex
}
//new and init a global value
func NewInt(val int) *AutoLockGblInt{
 p := &AutoLockGblInt{}
 p.val = val
 return p
}
//get value, if modify is disable, lock is unneeded
func (me *AutoLockGblInt) Get() (r int) {
 me.lock.RLock()
 defer me.lock.RUnlock()
 r = me.val
 return
}
//set value, if modify is disable, delete this function
func (me *AutoLockGblInt) Set(val int) (r int) {
 me.lock.Lock()
 defer me.lock.Unlock()
 r = me.val
 me.val = val
 return
}
 
/////////////////////////////////example_gpg_const_str.go
// This file was auto-generated by [gpg] tool
// Last modify at: 2014-01-21 13:06:46.6408372 +0800 +0800
// !!!!!!!!!NEVER MODIFY IT MANUALLY!!!!!!!!!
//Copyright @Ally 2014. All rights reserved.
//Version:   1.0.0
//Author:   [email protected]
//Blog site: http://blog.sina.com.cn/ally2014
//This is an example of using gpg tool forgeneric-programming
//this is an example of using gpg to define an auto-lock globalvalue with generic type
//it will be realized to real go code by gpg tool through the .gpgfile with the same name
package example
import (
 //"sync"
)
//auto locked global value
type AutoLockGblConstStr struct {
 val  string
 //lock sync.RWMutex
}
//new and init a global value
func NewConstStr(val string) *AutoLockGblConstStr{
 p := &AutoLockGblConstStr{}
 p.val = val
 return p
}
//get value, if modify is disable, lock is unneeded
func (me *AutoLockGblConstStr) Get() (r string) {
// me.lock.RLock()
// defer me.lock.RUnlock()
 r = me.val
 return
}
//set value, if modify is disable, delete this function
//func (me *AutoLockGblConstStr) Set(val string) (r string) {
// me.lock.Lock()
// defer me.lock.Unlock()
// r = me.val
// me.val = val
// return
//}


這樣基本可以滿足golang對泛型的需求,而不需要付出額外代價。

本博客原創博文版權所有 @[email protected]
僅供交流學習使用用於商業用途請聯繫原作者 
轉載請註明出處:http://blog.sina.com.cn/ally2014

[1] gpg源碼   https://github.com/vipally/gpg
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章