2014-07-11 23:12:35 +00:00
|
|
|
# Use in Go
|
|
|
|
|
|
|
|
There's experimental support for reading FlatBuffers in Go. Generate code
|
|
|
|
for Go with the `-g` option to `flatc`.
|
|
|
|
|
|
|
|
See `go_test.go` for an example. You import the generated code, read a
|
|
|
|
FlatBuffer binary file into a `[]byte`, which you pass to the
|
|
|
|
`GetRootAsMonster` function:
|
|
|
|
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
2014-07-11 23:12:35 +00:00
|
|
|
import (
|
|
|
|
example "MyGame/Example"
|
|
|
|
flatbuffers "github.com/google/flatbuffers/go"
|
|
|
|
|
|
|
|
io/ioutil
|
|
|
|
)
|
|
|
|
|
|
|
|
buf, err := ioutil.ReadFile("monster.dat")
|
|
|
|
// handle err
|
|
|
|
monster := example.GetRootAsMonster(buf, 0)
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2014-07-11 23:12:35 +00:00
|
|
|
|
|
|
|
Now you can access values like this:
|
|
|
|
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
2014-07-11 23:12:35 +00:00
|
|
|
hp := monster.Hp()
|
|
|
|
pos := monster.Pos(nil)
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2014-07-11 23:12:35 +00:00
|
|
|
|
|
|
|
Note that whenever you access a new object like in the `Pos` example above,
|
|
|
|
a new temporary accessor object gets created. If your code is very performance
|
|
|
|
sensitive (you iterate through a lot of objects), you can replace nil with a
|
|
|
|
pointer to a `Vec3` object you've already created. This allows
|
|
|
|
you to reuse it across many calls and reduce the amount of object allocation
|
|
|
|
(and thus garbage collection) your program does.
|
|
|
|
|
|
|
|
To access vectors you pass an extra index to the
|
|
|
|
vector field accessor. Then a second method with the same name suffixed
|
|
|
|
by `Length` let's you know the number of elements you can access:
|
|
|
|
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
2014-07-11 23:12:35 +00:00
|
|
|
for i := 0; i < monster.InventoryLength(); i++ {
|
|
|
|
monster.Inventory(i) // do something here
|
|
|
|
}
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2014-07-11 23:12:35 +00:00
|
|
|
|
|
|
|
You can also construct these buffers in Go using the functions found in the
|
|
|
|
generated code, and the FlatBufferBuilder class:
|
|
|
|
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
2014-07-11 23:12:35 +00:00
|
|
|
builder := flatbuffers.NewBuilder(0)
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2014-07-11 23:12:35 +00:00
|
|
|
|
|
|
|
Create strings:
|
|
|
|
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
2014-07-11 23:12:35 +00:00
|
|
|
str := builder.CreateString("MyMonster")
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2014-07-11 23:12:35 +00:00
|
|
|
|
|
|
|
Create a table with a struct contained therein:
|
|
|
|
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
2014-07-11 23:12:35 +00:00
|
|
|
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.MonsterAddTest_Type(builder, 1)
|
|
|
|
example.MonsterAddTest(builder, mon2)
|
|
|
|
example.MonsterAddTest4(builder, test4s)
|
|
|
|
mon := example.MonsterEnd(builder)
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2014-07-11 23:12:35 +00:00
|
|
|
|
|
|
|
Unlike C++, Go does not support table creation functions like 'createMonster()'.
|
|
|
|
This is to create the buffer without
|
|
|
|
using temporary object allocation (since the `Vec3` is an inline component of
|
|
|
|
`Monster`, it has to be created right where it is added, whereas the name and
|
2014-10-24 18:15:37 +00:00
|
|
|
the inventory are not inline, and **must** be created outside of the table
|
|
|
|
creation sequence).
|
2014-07-11 23:12:35 +00:00
|
|
|
Structs do have convenient methods that allow you to construct them in one call.
|
|
|
|
These also have arguments for nested structs, e.g. if a struct has a field `a`
|
|
|
|
and a nested struct field `b` (which has fields `c` and `d`), then the arguments
|
|
|
|
will be `a`, `c` and `d`.
|
|
|
|
|
|
|
|
Vectors also use this start/end pattern to allow vectors of both scalar types
|
|
|
|
and structs:
|
|
|
|
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
|
2014-07-11 23:12:35 +00:00
|
|
|
example.MonsterStartInventoryVector(builder, 5)
|
|
|
|
for i := 4; i >= 0; i-- {
|
|
|
|
builder.PrependByte(byte(i))
|
|
|
|
}
|
|
|
|
inv := builder.EndVector(5)
|
2014-10-06 17:43:02 +00:00
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
2014-07-11 23:12:35 +00:00
|
|
|
|
|
|
|
The generated method 'StartInventoryVector' is provided as a convenience
|
|
|
|
function which calls 'StartVector' with the correct element size of the vector
|
|
|
|
type which in this case is 'ubyte' or 1 byte per vector element.
|
|
|
|
You pass the number of elements you want to write.
|
|
|
|
You write the elements backwards since the buffer
|
2014-10-24 18:15:37 +00:00
|
|
|
is being constructed back to front. You then pass `inv` to the corresponding
|
|
|
|
`Add` call when you construct the table containing it afterwards.
|
2014-07-11 23:12:35 +00:00
|
|
|
|
|
|
|
There are `Prepend` functions for all the scalar types. You use
|
|
|
|
`PrependUOffset` for any previously constructed objects (such as other tables,
|
|
|
|
strings, vectors). For structs, you use the appropriate `create` function
|
|
|
|
in-line, as shown above in the `Monster` example.
|
|
|
|
|
2014-10-24 18:15:37 +00:00
|
|
|
Once you're done constructing a buffer, you call `Finish` with the root object
|
|
|
|
offset (`mon` in the example above). Your data now resides in Builder.Bytes.
|
|
|
|
Important to note is that the real data starts at the index indicated by Head(),
|
|
|
|
for Offset() bytes (this is because the buffer is constructed backwards).
|
|
|
|
If you wanted to read the buffer right after creating it (using
|
|
|
|
`GetRootAsMonster` above), the second argument, instead of `0` would thus
|
|
|
|
also be `Head()`.
|
|
|
|
|
2014-07-11 23:12:35 +00:00
|
|
|
## Text Parsing
|
|
|
|
|
|
|
|
There currently is no support for parsing text (Schema's and JSON) directly
|
|
|
|
from Go, though you could use the C++ parser through cgo. Please see the
|
|
|
|
C++ documentation for more on text parsing.
|