0
点赞
收藏
分享

微信扫一扫

FlatBuffers使用记录(Golang)


              试用了下FlatBuffers,把一些东东记录一下。

 FlatBuffers 官网:​​ http://google.github.io/flatbuffers/md__go_usage.html​​

它支持生成Go语言相关的东西,总的使用步骤如下: 

 

1. 定义IDL 接口定义文件,通常命名为.fbs     


    参考: Writing a schema 


     

​​http://google.github.io/flatbuffers/md__schemas.html​​



 2. 利用flatc 解析生成语言的文件

     flatc


     参考:  Using the schema compiler


     

​​ http://google.github.io/flatbuffers/md__compiler.html​​



      生成Go的参数:


       -g : Generate Go classes. Skipped for data.


 3. 在Go工程中安装FlatBuffers的Go支持包,就可以在代码直接使用了.        


 再详细说说FlatBuffers的一些特性。先上一份.fbs的例子:  

// example IDL file

namespace MyGame;

attribute "priority";

enum Color : byte { Red = 1, Green, Blue }

///union Any { Monster, Weapon, Pickup }
//union Any { Monster}
union Any { Monster, Weapon}

struct Vec3 {
x:float;
y:float;
z:float;
}

/// 注释
table Monster {
pos:Vec3;
mana:short = 150;
hp:short = 100;
name:string;
friendly:bool = false (deprecated, priority: 1);
inventory:[ubyte];
color:Color = Blue;
test:Any;
}

table Weapon {
pos:Vec3;
mana:short = 150;
}

root_type Monster;
root_type Weapon;

依上面的IDL作例子来说明一下.



IDL生成结果:

   会在MyGame下,生成Any.go,Color.go,Monster.go,Vec3.go,Weapon.go


     

5个go文件 

     protobuf则不会,protobuf会全部生成到一个.pb.go文件中.这么比起来,FlatBuffers灵活度更高些.


     


格式分析:

"namespace MyGame;" :

    会生成对应的MyGame目录



     "mana:short = 150;" :

           可以直接指定数据类型及默认值,且非常直观。


    


     

" table Monster { pos:Vec3; ":

           table可以直接嵌套struct



 

   "friendly:bool = false (deprecated, priority: 1);" :

          通过指定deprecated,可以删除掉此字段。



   

 attribute "priority" :

          定义了priority关键字,用在friendly上,但从生成的Go文件来看,没看出有啥意义。


       感觉可以忽略.


       


     

"union Any { Monster, Weapon}" :    


         union相关的东西用在 "test:Any;" 上.


       生成一个Any.go文件,里面的内容:          

const (
AnyNONE = 0
AnyMonster = 1
AnyWeapon = 2
)

       可以看到相当于一个enum类型。



   

"root_type Monster;root_type Weapon;"
          root_type的作用:

             在其table生成的go文件中,除Table中字段会生成相关函数外,


             

会另外生成GetRootAsMonster()函数,便于调用

                func GetRootAsMonster(buf []byte, offset flatbuffers.UOffsetT) *Monster {   


             如不用也可,没有太大影响。



    


格式其它:
    注释:

      在FlatBuffers中用 "

///" 来表示。且此注释会带入到生成的源码文件中。



   

效验:

       1. 当使用了未定义的类型或定义时,会报错


       2. 依顺序解析,如把最末的root_type Monster;提到table Monster前面,也会报错



   

required/optional :

       struct的每个字段都为required


       table的每个字段都默认都是optional,但可以指定为required


     


 

  指定Table字段函数生成顺序:   

/// 加id指定生成顺序
table Monster {
pos:Vec3 (id: 0);
mana:short = 150 (id: 3);
hp:short = 100 (id: 1);
name:string (id: 2);
//friendly:bool = false (deprecated, priority: 1);
friendly:bool = false (deprecated,id: 4);
//friendly:bool = false (priority: 1);
inventory:[ubyte] (id: 6);
color:Color = Blue (id: 5);
test:Any (id: 8);
}

依此为例,会按id指定顺序生成相关函数.
     注意:
        如有加id,则table中所有字段都要加id才可通过
        对于Any,可以看到id为8,而不是按顺序来的7.原来是它会生成:
        func (rcv *Monster) TestType() byte {}
        func (rcv *Monster) Test(obj *flatbuffers.Table) bool {}
        即隐含一个Type的字段。所以要加1. 即union型的,其id为{}内总个数加1.


   支持.fbs文件的嵌套:

       可以用 include "include_test1.fbs"; 形式,将其它.fbs文件嵌套进来。



使用方法:    

    取值:

buf, err := ioutil.ReadFile("monster.dat")
offset := 0
monster := example.GetRootAsMonster(buf, offset)
got := monster.Hp()

直接得到即可。



赋值:

可参考此代码:

builder := flatbuffers.NewBuilder(0)

str := builder.CreateString("MyMonster")
example.MonsterStart(builder)
example.MonsterAddPos(builder, example.CreateVec3(builder, 1.0, 2.0, 3.0, 3.0, 4, 5, 6))
example.MonsterAddHp(builder, 80)
example.MonsterAddName(builder, str)
example.MonsterAddInventory(builder, inv)
example.MonsterAddTestType(builder, 1)
// example.MonsterAddTest(builder, mon2)
// example.MonsterAddTest4(builder, test4s)
_ = example.MonsterEnd(builder)


         就到这了,速度啥的没做对比。 总的感觉是FlatBuffers定义起来简单,直观。


对Go支持很好,特别是分别生成一个个对应.go文件这点比较爽。其它待看。


举报

相关推荐

0 条评论