diff --git a/go/sizes.go b/go/sizes.go index e72b44f8615cf81aba7f97f89f75f1787dc1f604..ba221698455fd2f3d24bbd25e39759aa540ad40a 100644 --- a/go/sizes.go +++ b/go/sizes.go @@ -1,7 +1,7 @@ package flatbuffers import ( - "unsafe" + "unsafe" ) const ( diff --git a/samples/sample_binary.go b/samples/sample_binary.go index 7a36e6a8a350f4dd6e9e0ab771613dd41e685c22..e04650be6d7bc8a7c346c56e42269c959d5493c3 100644 --- a/samples/sample_binary.go +++ b/samples/sample_binary.go @@ -19,147 +19,147 @@ package main import ( - flatbuffers "github.com/google/flatbuffers/go" - "fmt" - "strconv" - sample "MyGame/Sample" + sample "MyGame/Sample" + "fmt" + flatbuffers "github.com/google/flatbuffers/go" + "strconv" ) // Example how to use Flatbuffers to create and read binary buffers. func main() { - builder := flatbuffers.NewBuilder(0) - - // Create some weapons for our Monster ("Sword" and "Axe"). - weaponOne := builder.CreateString("Sword") - weaponTwo := builder.CreateString("Axe") - - sample.WeaponStart(builder) - sample.WeaponAddName(builder, weaponOne) - sample.WeaponAddDamage(builder, 3) - sword := sample.WeaponEnd(builder) - - sample.WeaponStart(builder) - sample.WeaponAddName(builder, weaponTwo) - sample.WeaponAddDamage(builder, 5) - axe := sample.WeaponEnd(builder) - - // Serialize the FlatBuffer data. - name := builder.CreateString("Orc") - - sample.MonsterStartInventoryVector(builder, 10) - // Note: Since we prepend the bytes, this loop iterates in reverse. - for i := 9; i >= 0; i-- { - builder.PrependByte(byte(i)) - } - inv := builder.EndVector(10) - - sample.MonsterStartWeaponsVector(builder, 2) - // Note: Since we prepend the weapons, prepend in reverse order. - builder.PrependUOffsetT(axe) - builder.PrependUOffsetT(sword) - weapons := builder.EndVector(2) - - pos := sample.CreateVec3(builder, 1.0, 2.0, 3.0) - - sample.MonsterStart(builder) - sample.MonsterAddPos(builder, pos) - sample.MonsterAddHp(builder, 300) - sample.MonsterAddName(builder, name) - sample.MonsterAddInventory(builder, inv) - sample.MonsterAddColor(builder, sample.ColorRed) - sample.MonsterAddWeapons(builder, weapons) - sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon) - sample.MonsterAddEquipped(builder, axe) - orc := sample.MonsterEnd(builder) - - builder.Finish(orc) - - // We now have a FlatBuffer that we could store on disk or send over a network. - - // ...Saving to file or sending over a network code goes here... - - // Instead, we are going to access this buffer right away (as if we just received it). - - buf := builder.FinishedBytes() - - // Note: We use `0` for the offset here, since we got the data using the - // `builder.FinishedBytes()` method. This simulates the data you would store/receive in your - // FlatBuffer. If you wanted to read from the `builder.Bytes` directly, you would need to - // pass in the offset of `builder.Head()`, as the builder actually constructs the buffer - // backwards. - monster := sample.GetRootAsMonster(buf, 0) - - // Note: We did not set the `mana` field explicitly, so we get the - // default value. - assert(monster.Mana() == 150, "`monster.Mana()`", strconv.Itoa(int(monster.Mana())), "150") - assert(monster.Hp() == 300, "`monster.Hp()`", strconv.Itoa(int(monster.Hp())), "300") - assert(string(monster.Name()) == "Orc", "`string(monster.Name())`", string(monster.Name()), - "\"Orc\"") - assert(monster.Color() == sample.ColorRed, "`monster.Color()`", - strconv.Itoa(int(monster.Color())), strconv.Itoa(int(sample.ColorRed))) - - // Note: Whenever you access a new object, like in `Pos()`, a new temporary accessor object - // gets created. If your code is very performance sensitive, you can pass in a pointer to an - // existing `Vec3` instead of `nil`. This allows you to reuse it across many calls to reduce - // the amount of object allocation/garbage collection. - assert(monster.Pos(nil).X() == 1.0, "`monster.Pos(nil).X()`", - strconv.FormatFloat(float64(monster.Pos(nil).X()), 'f', 1, 32), "1.0") - assert(monster.Pos(nil).Y() == 2.0, "`monster.Pos(nil).Y()`", - strconv.FormatFloat(float64(monster.Pos(nil).Y()), 'f', 1, 32), "2.0") - assert(monster.Pos(nil).Z() == 3.0, "`monster.Pos(nil).Z()`", - strconv.FormatFloat(float64(monster.Pos(nil).Z()), 'f', 1, 32), "3.0") - - // For vectors, like `Inventory`, they have a method suffixed with 'Length' that can be used - // to query the length of the vector. You can index the vector by passing an index value - // into the accessor. - for i := 0; i < monster.InventoryLength(); i++ { - assert(monster.Inventory(i) == byte(i), "`monster.Inventory(i)`", - strconv.Itoa(int(monster.Inventory(i))), strconv.Itoa(int(byte(i)))) - } - - expectedWeaponNames := []string{"Sword", "Axe"} - expectedWeaponDamages := []int{3, 5} - weapon := new(sample.Weapon) // We need a `sample.Weapon` to pass into `monster.Weapons()` - // to capture the output of that function. - for i := 0; i < monster.WeaponsLength(); i++ { - if monster.Weapons(weapon, i) { - assert(string(weapon.Name()) == expectedWeaponNames[i], "`weapon.Name()`", - string(weapon.Name()), expectedWeaponNames[i]) - assert(int(weapon.Damage()) == expectedWeaponDamages[i], - "`weapon.Damage()`", strconv.Itoa(int(weapon.Damage())), - strconv.Itoa(expectedWeaponDamages[i])) - } - } - - // For FlatBuffer `union`s, you can get the type of the union, as well as the union - // data itself. - assert(monster.EquippedType() == sample.EquipmentWeapon, "`monster.EquippedType()`", - strconv.Itoa(int(monster.EquippedType())), strconv.Itoa(int(sample.EquipmentWeapon))) - - unionTable := new(flatbuffers.Table) - if monster.Equipped(unionTable) { - // An example of how you can appropriately convert the table depending on the - // FlatBuffer `union` type. You could add `else if` and `else` clauses to handle - // other FlatBuffer `union` types for this field. (Similarly, this could be - // done in a switch statement.) - if monster.EquippedType() == sample.EquipmentWeapon { - unionWeapon := new(sample.Weapon) - unionWeapon.Init(unionTable.Bytes, unionTable.Pos) - - assert(string(unionWeapon.Name()) == "Axe", "`unionWeapon.Name()`", - string(unionWeapon.Name()), "Axe") - assert(int(unionWeapon.Damage()) == 5, "`unionWeapon.Damage()`", - strconv.Itoa(int(unionWeapon.Damage())), strconv.Itoa(5)) - } - } - - fmt.Printf("The FlatBuffer was successfully created and verified!\n") + builder := flatbuffers.NewBuilder(0) + + // Create some weapons for our Monster ("Sword" and "Axe"). + weaponOne := builder.CreateString("Sword") + weaponTwo := builder.CreateString("Axe") + + sample.WeaponStart(builder) + sample.WeaponAddName(builder, weaponOne) + sample.WeaponAddDamage(builder, 3) + sword := sample.WeaponEnd(builder) + + sample.WeaponStart(builder) + sample.WeaponAddName(builder, weaponTwo) + sample.WeaponAddDamage(builder, 5) + axe := sample.WeaponEnd(builder) + + // Serialize the FlatBuffer data. + name := builder.CreateString("Orc") + + sample.MonsterStartInventoryVector(builder, 10) + // Note: Since we prepend the bytes, this loop iterates in reverse. + for i := 9; i >= 0; i-- { + builder.PrependByte(byte(i)) + } + inv := builder.EndVector(10) + + sample.MonsterStartWeaponsVector(builder, 2) + // Note: Since we prepend the weapons, prepend in reverse order. + builder.PrependUOffsetT(axe) + builder.PrependUOffsetT(sword) + weapons := builder.EndVector(2) + + pos := sample.CreateVec3(builder, 1.0, 2.0, 3.0) + + sample.MonsterStart(builder) + sample.MonsterAddPos(builder, pos) + sample.MonsterAddHp(builder, 300) + sample.MonsterAddName(builder, name) + sample.MonsterAddInventory(builder, inv) + sample.MonsterAddColor(builder, sample.ColorRed) + sample.MonsterAddWeapons(builder, weapons) + sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon) + sample.MonsterAddEquipped(builder, axe) + orc := sample.MonsterEnd(builder) + + builder.Finish(orc) + + // We now have a FlatBuffer that we could store on disk or send over a network. + + // ...Saving to file or sending over a network code goes here... + + // Instead, we are going to access this buffer right away (as if we just received it). + + buf := builder.FinishedBytes() + + // Note: We use `0` for the offset here, since we got the data using the + // `builder.FinishedBytes()` method. This simulates the data you would store/receive in your + // FlatBuffer. If you wanted to read from the `builder.Bytes` directly, you would need to + // pass in the offset of `builder.Head()`, as the builder actually constructs the buffer + // backwards. + monster := sample.GetRootAsMonster(buf, 0) + + // Note: We did not set the `mana` field explicitly, so we get the + // default value. + assert(monster.Mana() == 150, "`monster.Mana()`", strconv.Itoa(int(monster.Mana())), "150") + assert(monster.Hp() == 300, "`monster.Hp()`", strconv.Itoa(int(monster.Hp())), "300") + assert(string(monster.Name()) == "Orc", "`string(monster.Name())`", string(monster.Name()), + "\"Orc\"") + assert(monster.Color() == sample.ColorRed, "`monster.Color()`", + strconv.Itoa(int(monster.Color())), strconv.Itoa(int(sample.ColorRed))) + + // Note: Whenever you access a new object, like in `Pos()`, a new temporary accessor object + // gets created. If your code is very performance sensitive, you can pass in a pointer to an + // existing `Vec3` instead of `nil`. This allows you to reuse it across many calls to reduce + // the amount of object allocation/garbage collection. + assert(monster.Pos(nil).X() == 1.0, "`monster.Pos(nil).X()`", + strconv.FormatFloat(float64(monster.Pos(nil).X()), 'f', 1, 32), "1.0") + assert(monster.Pos(nil).Y() == 2.0, "`monster.Pos(nil).Y()`", + strconv.FormatFloat(float64(monster.Pos(nil).Y()), 'f', 1, 32), "2.0") + assert(monster.Pos(nil).Z() == 3.0, "`monster.Pos(nil).Z()`", + strconv.FormatFloat(float64(monster.Pos(nil).Z()), 'f', 1, 32), "3.0") + + // For vectors, like `Inventory`, they have a method suffixed with 'Length' that can be used + // to query the length of the vector. You can index the vector by passing an index value + // into the accessor. + for i := 0; i < monster.InventoryLength(); i++ { + assert(monster.Inventory(i) == byte(i), "`monster.Inventory(i)`", + strconv.Itoa(int(monster.Inventory(i))), strconv.Itoa(int(byte(i)))) + } + + expectedWeaponNames := []string{"Sword", "Axe"} + expectedWeaponDamages := []int{3, 5} + weapon := new(sample.Weapon) // We need a `sample.Weapon` to pass into `monster.Weapons()` + // to capture the output of that function. + for i := 0; i < monster.WeaponsLength(); i++ { + if monster.Weapons(weapon, i) { + assert(string(weapon.Name()) == expectedWeaponNames[i], "`weapon.Name()`", + string(weapon.Name()), expectedWeaponNames[i]) + assert(int(weapon.Damage()) == expectedWeaponDamages[i], + "`weapon.Damage()`", strconv.Itoa(int(weapon.Damage())), + strconv.Itoa(expectedWeaponDamages[i])) + } + } + + // For FlatBuffer `union`s, you can get the type of the union, as well as the union + // data itself. + assert(monster.EquippedType() == sample.EquipmentWeapon, "`monster.EquippedType()`", + strconv.Itoa(int(monster.EquippedType())), strconv.Itoa(int(sample.EquipmentWeapon))) + + unionTable := new(flatbuffers.Table) + if monster.Equipped(unionTable) { + // An example of how you can appropriately convert the table depending on the + // FlatBuffer `union` type. You could add `else if` and `else` clauses to handle + // other FlatBuffer `union` types for this field. (Similarly, this could be + // done in a switch statement.) + if monster.EquippedType() == sample.EquipmentWeapon { + unionWeapon := new(sample.Weapon) + unionWeapon.Init(unionTable.Bytes, unionTable.Pos) + + assert(string(unionWeapon.Name()) == "Axe", "`unionWeapon.Name()`", + string(unionWeapon.Name()), "Axe") + assert(int(unionWeapon.Damage()) == 5, "`unionWeapon.Damage()`", + strconv.Itoa(int(unionWeapon.Damage())), strconv.Itoa(5)) + } + } + + fmt.Printf("The FlatBuffer was successfully created and verified!\n") } // A helper function to print out if an assertion failed. func assert(assertPassed bool, codeExecuted string, actualValue string, expectedValue string) { - if assertPassed == false { - panic("Assert failed! " + codeExecuted + " (" + actualValue + - ") was not equal to " + expectedValue + ".") - } + if assertPassed == false { + panic("Assert failed! " + codeExecuted + " (" + actualValue + + ") was not equal to " + expectedValue + ".") + } } diff --git a/tests/go_test.go b/tests/go_test.go index 9aba3e1bcdc9e3feac604059733599966365cd03..421aa4b91e9fe417a3ca8c22428813516a0bbeea 100644 --- a/tests/go_test.go +++ b/tests/go_test.go @@ -1251,9 +1251,9 @@ func CheckVtableDeduplication(fail func(string, ...interface{})) { len(want), want, len(got), got) } - table0 := &flatbuffers.Table{b.Bytes, flatbuffers.UOffsetT(len(b.Bytes)) - obj0} - table1 := &flatbuffers.Table{b.Bytes, flatbuffers.UOffsetT(len(b.Bytes)) - obj1} - table2 := &flatbuffers.Table{b.Bytes, flatbuffers.UOffsetT(len(b.Bytes)) - obj2} + table0 := &flatbuffers.Table{Bytes: b.Bytes, UOffset: flatbuffers.UOffsetT(len(b.Bytes)) - obj0} + table1 := &flatbuffers.Table{Bytes: b.Bytes, UOffset: flatbuffers.UOffsetT(len(b.Bytes)) - obj1} + table2 := &flatbuffers.Table{Bytes: b.Bytes, UOffset: flatbuffers.UOffsetT(len(b.Bytes)) - obj2} testTable := func(tab *flatbuffers.Table, a flatbuffers.VOffsetT, b, c, d byte) { // vtable size