or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cpp-core.mdflexbuffers.mdgo.mdindex.mdjava.mdjavascript.mdpython.mdrust.mdschema-compiler.mdverification.md
tile.json

go.mddocs/

Go

Go implementation of FlatBuffers leveraging Go's memory management and providing idiomatic Go interfaces for FlatBuffer operations. The Go binding maintains zero-copy deserialization benefits while integrating seamlessly with Go's type system and concurrency features.

Capabilities

Installation and Imports

Install FlatBuffers for Go and import the necessary components.

# Install FlatBuffers Go package
go get github.com/google/flatbuffers/go

# Or with specific version
go get github.com/google/flatbuffers/go@v25.2.10
// Core imports
import (
    flatbuffers "github.com/google/flatbuffers/go"
)

// Common additional imports
import (
    "fmt"
    "io/ioutil"
    "os"
)

Builder Type

Main builder type for constructing FlatBuffer data in Go applications.

type Builder struct {
    // Internal fields (not exported)
}

/**
 * Create new FlatBuffer builder
 * @param initialSize Initial buffer size in bytes
 * @return New Builder instance
 */
func NewBuilder(initialSize int) *Builder

/**
 * Reset builder for reuse, keeping allocated memory
 */
func (b *Builder) Reset()

/**
 * Get current write position/size
 * @return Current offset
 */
func (b *Builder) Offset() UOffsetT

/**
 * Create string and return its offset
 * @param s String to store
 * @return Offset to string
 */
func (b *Builder) CreateString(s string) UOffsetT

/**
 * Create byte vector from slice
 * @param v Byte slice to store
 * @return Offset to vector
 */
func (b *Builder) CreateByteVector(v []byte) UOffsetT

/**
 * Start building a vector
 * @param elemSize Size of each element
 * @param numElems Number of elements
 * @param alignment Required alignment
 */
func (b *Builder) StartVector(elemSize, numElems, alignment int)

/**
 * End vector construction
 * @return Offset to completed vector
 */
func (b *Builder) EndVector() UOffsetT

/**
 * Start building a table
 * @param numFields Number of fields in table
 */  
func (b *Builder) StartObject(numFields int)

/**
 * Add slot for field (prepares vtable entry)
 * @param slotnum Field slot number
 */
func (b *Builder) Slot(slotnum int)

/**
 * Add byte value to current position
 * @param x Byte value
 */
func (b *Builder) PrependByte(x byte)

/**
 * Add uint8 value to current position
 * @param x Uint8 value  
 */
func (b *Builder) PrependUint8(x uint8)

/**
 * Add int8 value to current position
 * @param x Int8 value
 */
func (b *Builder) PrependInt8(x int8)

/**
 * Add uint16 value to current position
 * @param x Uint16 value
 */
func (b *Builder) PrependUint16(x uint16)

/**
 * Add int16 value to current position
 * @param x Int16 value
 */
func (b *Builder) PrependInt16(x int16)

/**
 * Add uint32 value to current position
 * @param x Uint32 value
 */
func (b *Builder) PrependUint32(x uint32)

/**
 * Add int32 value to current position
 * @param x Int32 value
 */
func (b *Builder) PrependInt32(x int32)

/**
 * Add uint64 value to current position
 * @param x Uint64 value
 */
func (b *Builder) PrependUint64(x uint64)

/**
 * Add int64 value to current position
 * @param x Int64 value
 */
func (b *Builder) PrependInt64(x int64)

/**
 * Add float32 value to current position
 * @param x Float32 value
 */
func (b *Builder) PrependFloat32(x float32)

/**
 * Add float64 value to current position
 * @param x Float64 value
 */
func (b *Builder) PrependFloat64(x float64)

/**
 * Add offset value relative to current position
 * @param off Offset value
 */
func (b *Builder) PrependUOffsetTRelative(off UOffsetT)

/**
 * End table construction
 * @return Offset to completed table
 */
func (b *Builder) EndObject() UOffsetT

/**
 * Finish buffer with root table
 * @param rootTable Offset to root table
 */
func (b *Builder) Finish(rootTable UOffsetT)

/**
 * Finish buffer with root table and file identifier
 * @param rootTable Offset to root table
 * @param fileIdentifier 4-byte file identifier
 */
func (b *Builder) FinishWithFileIdentifier(rootTable UOffsetT, fileIdentifier []byte)

/**
 * Finish buffer with size prefix
 * @param rootTable Offset to root table
 */
func (b *Builder) FinishSizePrefixed(rootTable UOffsetT)

/**
 * Get finished buffer as byte slice
 * @return Byte slice containing FlatBuffer data
 */
func (b *Builder) FinishedBytes() []byte

/**
 * Get buffer size
 * @return Size in bytes
 */
func (b *Builder) Size() int

Usage Example:

package main

import (
    flatbuffers "github.com/google/flatbuffers/go"
    "fmt"
)

func main() {
    // Create builder
    builder := flatbuffers.NewBuilder(1024)

    // Create string  
    name := builder.CreateString("Player")

    // Create vector
    scores := []int32{100, 200, 300, 400, 500}
    builder.StartVector(4, len(scores), 4)
    for i := len(scores) - 1; i >= 0; i-- {
        builder.PrependInt32(scores[i])
    }
    scoresOffset := builder.EndVector()

    // Create table
    builder.StartObject(3)
    builder.PrependUOffsetTRelative(name)      // name field (slot 0)
    builder.Slot(0)
    builder.PrependInt32(42)                   // level field (slot 1)  
    builder.Slot(1)
    builder.PrependUOffsetTRelative(scoresOffset) // scores field (slot 2)
    builder.Slot(2)
    player := builder.EndObject()

    // Finish buffer
    builder.Finish(player)

    // Get binary data
    buffer := builder.FinishedBytes()
    fmt.Printf("Buffer size: %d bytes\n", len(buffer))
}

Type Definitions

Core type definitions used throughout the FlatBuffers Go API.

// Basic offset and size types
type UOffsetT uint32    // Unsigned offset type  
type SOffsetT int32     // Signed offset type
type VOffsetT uint16    // VTable offset type

// Constants
const (
    SizeUOffsetT = 4          // Size of UOffsetT in bytes
    SizeSOffsetT = 4          // Size of SOffsetT in bytes  
    SizeVOffsetT = 2          // Size of VOffsetT in bytes
    FileIdentifierLength = 4   // Length of file identifier
    SizePrefixLength = 4      // Size prefix length
)

// Table interface for generated table types
type Table struct {
    Bytes []byte    // Buffer containing table data
    Pos   UOffsetT  // Position of table in buffer
}

/**
 * Get field offset from vtable
 * @param table Table instance
 * @param vtableOffset Offset in vtable
 * @return Field offset or 0 if not present
 */
func (t *Table) Offset(vtableOffset VOffsetT) VOffsetT

/**
 * Get indirect offset (for tables, vectors, strings)
 * @param table Table instance  
 * @param offset Field offset
 * @return Indirect offset
 */
func (t *Table) Indirect(offset UOffsetT) UOffsetT

/**
 * Get string at offset
 * @param table Table instance
 * @param offset String offset
 * @return String value
 */
func (t *Table) String(offset UOffsetT) string

/**
 * Get byte slice at offset  
 * @param table Table instance
 * @param offset Offset to data
 * @param length Data length
 * @return Byte slice
 */
func (t *Table) ByteVector(offset UOffsetT) []byte

/**
 * Get vector length at offset
 * @param table Table instance
 * @param offset Vector offset  
 * @return Vector length
 */
func (t *Table) VectorLen(offset UOffsetT) int

/**
 * Get vector element position
 * @param table Table instance
 * @param offset Vector offset
 * @param i Element index
 * @param elemSize Element size in bytes
 * @return Element position
 */
func (t *Table) Vector(offset UOffsetT) UOffsetT

Generated Code Structure

When using flatc --go, the compiler generates Go code following these patterns.

// Example generated Go (from monster.fbs):

package MyGame

import (
    flatbuffers "github.com/google/flatbuffers/go"
)

// Vec3 struct definition
type Vec3 struct {
    X float32
    Y float32  
    Z float32
}

// Pack Vec3 into builder
func (v *Vec3) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
    builder.Prep(4, 12)
    builder.PrependFloat32(v.Z)
    builder.PrependFloat32(v.Y)
    builder.PrependFloat32(v.X)
    return builder.Offset()
}

// Monster table type
type Monster struct {
    _tab flatbuffers.Table
}

// Get Monster from buffer bytes at offset
func GetRootAsMonster(buf []byte, offset flatbuffers.UOffsetT) *Monster {
    n := flatbuffers.GetUOffsetT(buf[offset:])
    x := &Monster{}
    x.Init(buf, n+offset)
    return x
}

// Initialize Monster with buffer and position
func (rcv *Monster) Init(buf []byte, i flatbuffers.UOffsetT) {
    rcv._tab.Bytes = buf
    rcv._tab.Pos = i
}

// Get Monster table
func (rcv *Monster) Table() *flatbuffers.Table {
    return &rcv._tab
}

// Get position as Vec3
func (rcv *Monster) Pos(obj *Vec3) *Vec3 {
    o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
    if o != 0 {
        x := rcv._tab.Pos + o
        if obj == nil {
            obj = &Vec3{}
        }
        obj.X = flatbuffers.GetFloat32(rcv._tab.Bytes[x:])
        obj.Y = flatbuffers.GetFloat32(rcv._tab.Bytes[x+4:])
        obj.Z = flatbuffers.GetFloat32(rcv._tab.Bytes[x+8:])
        return obj
    }
    return nil
}

// Get mana value
func (rcv *Monster) Mana() int16 {
    o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
    if o != 0 {
        return flatbuffers.GetInt16(rcv._tab.Bytes[rcv._tab.Pos+o:])
    }
    return 150 // default value
}

// Get HP value  
func (rcv *Monster) Hp() int16 {
    o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
    if o != 0 {
        return flatbuffers.GetInt16(rcv._tab.Bytes[rcv._tab.Pos+o:])
    }
    return 100 // default value
}

// Get name string
func (rcv *Monster) Name() string {
    o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
    if o != 0 {
        return rcv._tab.String(rcv._tab.Pos + o)
    }
    return ""
}

// Get inventory item at index
func (rcv *Monster) Inventory(j int) uint8 {
    o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
    if o != 0 {
        a := rcv._tab.Vector(rcv._tab.Pos + o)
        return flatbuffers.GetUint8(rcv._tab.Bytes[a+flatbuffers.UOffsetT(j*1):])
    }
    return 0
}

// Get inventory vector length
func (rcv *Monster) InventoryLength() int {
    o := flatbuffers.UOffsetT(rcv._tab.Offset(14))  
    if o != 0 {
        return rcv._tab.VectorLen(rcv._tab.Pos + o)
    }
    return 0
}

// Get inventory as byte slice
func (rcv *Monster) InventoryBytes() []byte {
    o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
    if o != 0 {
        return rcv._tab.ByteVector(rcv._tab.Pos + o)
    }
    return nil
}

// Monster builder functions
func MonsterStart(builder *flatbuffers.Builder) {
    builder.StartObject(6)
}

func MonsterAddPos(builder *flatbuffers.Builder, pos flatbuffers.UOffsetT) {
    builder.PrependStructSlot(0, pos, 0)
}

func MonsterAddMana(builder *flatbuffers.Builder, mana int16) {
    builder.PrependInt16Slot(1, mana, 150)
}

func MonsterAddHp(builder *flatbuffers.Builder, hp int16) {
    builder.PrependInt16Slot(2, hp, 100)
}

func MonsterAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) {
    builder.PrependUOffsetTSlot(3, name, 0)
}

func MonsterAddInventory(builder *flatbuffers.Builder, inventory flatbuffers.UOffsetT) {
    builder.PrependUOffsetTSlot(5, inventory, 0)
}

func MonsterStartInventoryVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
    return builder.StartVector(1, numElems, 1)
}

func MonsterEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
    return builder.EndObject()
}

// Convenience function to create Monster
func MonsterCreate(builder *flatbuffers.Builder, pos flatbuffers.UOffsetT, mana int16, hp int16, name flatbuffers.UOffsetT, inventory flatbuffers.UOffsetT) flatbuffers.UOffsetT {
    MonsterStart(builder)
    MonsterAddPos(builder, pos)
    MonsterAddMana(builder, mana)
    MonsterAddHp(builder, hp)
    MonsterAddName(builder, name)
    MonsterAddInventory(builder, inventory)
    return MonsterEnd(builder)
}

Utility Functions

Utility functions for working with FlatBuffer data in Go.

// Read scalar values from byte slices
func GetUint8(buf []byte) uint8
func GetInt8(buf []byte) int8  
func GetUint16(buf []byte) uint16
func GetInt16(buf []byte) int16
func GetUint32(buf []byte) uint32
func GetInt32(buf []byte) int32
func GetUint64(buf []byte) uint64
func GetInt64(buf []byte) int64
func GetFloat32(buf []byte) float32
func GetFloat64(buf []byte) float64

// Get offset values
func GetUOffsetT(buf []byte) UOffsetT
func GetSOffsetT(buf []byte) SOffsetT
func GetVOffsetT(buf []byte) VOffsetT

// Buffer validation
func SizeUint32(buf []byte) uint32  // Get size prefix
func SizePrefixedBuffer(buf []byte) []byte  // Get buffer without size prefix

// String operations
func GetRootAsString(buf []byte, offset UOffsetT) string

File I/O and Concurrency

Working with files and Go's concurrency features.

import (
    "io/ioutil"
    "os"
    "sync"
    flatbuffers "github.com/google/flatbuffers/go"
)

// File operations
func SaveFlatBuffer(builder *flatbuffers.Builder, filename string) error {
    data := builder.FinishedBytes()
    return ioutil.WriteFile(filename, data, 0644)
}

func LoadFlatBuffer(filename string) ([]byte, error) {
    return ioutil.ReadFile(filename)
}

// Safe concurrent builder pool
type BuilderPool struct {
    pool sync.Pool
}

func NewBuilderPool(initialSize int) *BuilderPool {
    return &BuilderPool{
        pool: sync.Pool{
            New: func() interface{} {
                return flatbuffers.NewBuilder(initialSize)
            },
        },
    }
}

func (p *BuilderPool) Get() *flatbuffers.Builder {
    return p.pool.Get().(*flatbuffers.Builder)
}

func (p *BuilderPool) Put(builder *flatbuffers.Builder) {
    builder.Reset()
    p.pool.Put(builder)
}

// Concurrent processing example
func ProcessMonstersAsync(monsters []MonsterData) [][]byte {
    const numWorkers = 4
    pool := NewBuilderPool(1024)
    
    input := make(chan MonsterData, len(monsters))
    output := make(chan []byte, len(monsters))
    
    // Start workers
    var wg sync.WaitGroup
    for i := 0; i < numWorkers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            builder := pool.Get()
            defer pool.Put(builder)
            
            for monster := range input {
                // Build FlatBuffer from monster data
                result := buildMonster(builder, monster)
                output <- result
                builder.Reset()
            }
        }()
    }
    
    // Send work
    go func() {
        for _, monster := range monsters {
            input <- monster
        }
        close(input)
    }()
    
    // Wait and collect results
    go func() {
        wg.Wait()
        close(output)
    }()
    
    var results [][]byte
    for result := range output {
        results = append(results, result)
    }
    
    return results
}

Complete Usage Example:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    
    flatbuffers "github.com/google/flatbuffers/go"
    // Import generated package
    "example/MyGame"
)

func main() {
    // Create monster
    builder := flatbuffers.NewBuilder(1024)
    
    // Create components
    name := builder.CreateString("Dragon")
    pos := &MyGame.Vec3{X: 1.0, Y: 2.0, Z: 3.0}
    posOffset := pos.Pack(builder)
    
    // Create inventory
    inventoryData := []uint8{1, 2, 3, 4, 5}
    MyGame.MonsterStartInventoryVector(builder, len(inventoryData))
    for i := len(inventoryData) - 1; i >= 0; i-- {
        builder.PrependUint8(inventoryData[i])
    }
    inventory := builder.EndVector()
    
    // Build monster
    monster := MyGame.MonsterCreate(builder, posOffset, 200, 150, name, inventory)
    
    // Finish buffer
    builder.Finish(monster)
    buffer := builder.FinishedBytes()
    
    // Read the data back
    readMonster := MyGame.GetRootAsMonster(buffer, 0)
    
    fmt.Printf("Name: %s\n", readMonster.Name())
    fmt.Printf("HP: %d\n", readMonster.Hp())
    fmt.Printf("Mana: %d\n", readMonster.Mana())
    
    position := readMonster.Pos(nil)
    if position != nil {
        fmt.Printf("Position: %.1f, %.1f, %.1f\n", position.X, position.Y, position.Z)
    }
    
    fmt.Printf("Inventory size: %d\n", readMonster.InventoryLength())
    inventoryBytes := readMonster.InventoryBytes()
    for i, item := range inventoryBytes {
        fmt.Printf("Item %d: %d\n", i, item)
    }
    
    // Save to file
    if err := ioutil.WriteFile("monster.bin", buffer, 0644); err != nil {
        log.Fatal(err)
    }
    
    // Load from file
    loadedBuffer, err := ioutil.ReadFile("monster.bin")
    if err != nil {
        log.Fatal(err)
    }
    
    loadedMonster := MyGame.GetRootAsMonster(loadedBuffer, 0)
    fmt.Printf("Loaded name: %s\n", loadedMonster.Name())
}