1. 程式人生 > >[golang]讓golang支援泛型程式設計的一種方案

[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