使用接口的编码方法对以后扩展程序或者更新程序是非常方便的,其中一种使用接口 (interface) 为先注册后使用,如这里的 example: 先把实现了接口 Auditer 的实例 通过Regisgter注册到 AuditList 中再通过Executer根据 auditType 进行调用。
注册:实质就是一个 map,还搞个 注册 名词出来是为了更好的规范表达而已
package main
import "fmt"
type Auditer interface {
Audit() error
}
var AuditList map[string]Auditer
type A struct {
A int
Auditer
}
func (this A) Audit() error {
fmt.Printf("this.A: approve works %v\n", this.A)
return nil
}
type B struct {
B int
}
func (this B) Audit() error {
fmt.Printf("this.B: disapprove works %v\n", this.B)
return nil
}
func init() {
println("init")
AuditList = map[string]Auditer{}
}
func Regisgter(auditType string, auditInstance Auditer) {
AuditList[auditType] = auditInstance
}
func Executer(auditType string) error {
return AuditList[auditType].Audit()
// audit, ok := AuditList[auditType]
// if ok {
// if err := audit.Audit(); err != nil {
// return err
// }
// fmt.Printf("runs normally\n")
// return nil
// }
// return errors.New("unexpected get instance fail")
}
func main() {
a := A{A: 1000}
b := B{B: 9999}
Regisgter("approve", a)
Regisgter("disapprove", b)
if err := Executer("approve"); err != nil {
panic(err.Error())
}
return
}
update:2015-09-20:10:39:05
发现 google 中 golang 版本的 protocal buffers 中的文件 properties.go 也用到这个注册式的写法:
// A global registry of enum types.
// The generated code will register the generated maps by calling RegisterEnum.
var enumValueMaps = make(map[string]map[string]int32)
// RegisterEnum is called from the generated code to install the enum descriptor
// maps into the global table to aid parsing text format protocol buffers.
func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
if _, ok := enumValueMaps[typeName]; ok {
panic("proto: duplicate enum registered: " + typeName)
}
enumValueMaps[typeName] = valueMap
}