1.go OOP思想
首先go语言里面是没有面向对象的这一概念的,但是在实际的业务需求中,面向对象其实更为适用。因此在这里分享一想go语言中基本的面向对象的编程思路。
package oop
import "reflect"
var Types = make(map[string]reflect.Type)
//基类
type Base interface {
GetName()
}
//两个子类
type A struct {
Name string
}
type B struct {
Name string
}
//一个帮助类
type Helper struct {
Type string //用来区分Value的具体类型
Value Base
}
func init() {
Types["A"] = reflect.TypeOf(A{})
Types["B"] = reflect.TypeOf(B{})
}
基于上述代码来进行分析:
Base为一个接口类型,代码中实现了其两个子类A和B,另外借助于Helper类中的Type属性以及map表Types,我们在真正需要某一子类的时候,可以从根据Type从Type中拿到具体的子类对象。
2.OOP中MongoDB数据解析
非常注意:
在使用mongodb的时候,go语言中的一个类其实对应了数据库中的一张表,我们假设Hepler为一张表,由于Helper中包含了一个接口类型的数据(对应多态),因此在数据库数据进行解析的时候,就会报错,解决的方法是重写mongo引擎中的UnmarshalBSON(解析json的方法和解析mongo数据类似)
首先有一个方法Cast,可以根据Type实例化出一个对象。
如下:
func Cast(t string) Base{
ptrType := Types[t]
ptrNew := reflect.New(ptrType)
i:= ptrNew.Elem().Addr().Interface()
it:=i.(Base)
return it
}
接下来就是重写UnmarshalBson.
type Data struct {
Type SourceValueType `bson:"Type,omitempty" json:"Type,omitempty"`
Val bson.Raw`bson:"Val,omitempty" json:"Val,omitempty"`
}
func (d *Value) UnmarshalBSON(obj[]byte) error {
*h = Helper{}
data := &Data{}
err := bson.Unmarshal(obj, &data )
if err != nil {
return err
}
item := Cast(data.Type)
h.Type = data.Type
err= bson.Unmarshal(data.Val,item)
data.Val = item
return err
}
在上述代码中首先定义了一张新的表,为Data,为从数据库中去拿相应的数据,再Data中,Type则代表Helper中的Type,Data.val为bson.Raw类型,其可以接收数据库中任意类型的数据。因此A和B两种类型的数据都是可以放在Data.Val中的,在UnmarshalBSON函数中,首先根据byte数据obj将数据全部放入到data中,然后再根据data.Type去调用Cast来获取Base的其中的一个子类对象,最后调用原生的方法将data.Val解析到具体的多态对象中。