CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-flatbuffers

Memory efficient cross-platform serialization library with zero-copy deserialization supporting 15+ programming languages.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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())
}

docs

cpp-core.md

flexbuffers.md

go.md

index.md

java.md

javascript.md

python.md

rust.md

schema-compiler.md

verification.md

tile.json