using interface

使用接口的编码方法对以后扩展程序或者更新程序是非常方便的,其中一种使用接口 (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
}

2015-09-20