這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。本部落格原創博文著作權 @Allyvipally@gmail.com僅供交流學習使用用於商業用途請聯絡原作者 轉載請註明出處: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 exampleimport (
"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: vipally@gmail.com
//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 exampleimport (
"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: vipally@gmail.com
//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 exampleimport (
//"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
//}