View all results

Getting Started

This page walks through installing Ferret as a Go dependency, running a query, and working with the result.

Installation

Add the module to your project:

terminal
go get github.com/MontFerret/ferret/v2

Running a query

The simplest way to execute a query is engine.Run. It compiles the source, runs it in a fresh session, and returns the encoded output.

example.go
read-only
package main import ( "context" "fmt" "log" "github.com/MontFerret/ferret/v2" "github.com/MontFerret/ferret/v2/pkg/source" ) func main() { engine, err := ferret.New() if err != nil { log.Fatal(err) } defer engine.Close() output, err := engine.Run( context.Background(), source.NewAnonymous(`return { name: "Ferret", version: 2 }`), ) if err != nil { log.Fatal(err) } fmt.Println(string(output.Content)) // {"name":"Ferret","version":2} }

source.NewAnonymous wraps a query string into a *source.Source. For named sources use source.New(name, text) — the name appears in error messages and debug output.

Compiling and reusing a plan

When the same query runs many times — with different parameters, in different goroutines, or on a schedule — compile it once and create sessions from the resulting plan:

example.go
read-only
plan, err := engine.Compile(ctx, source.New("greeting", `return upper(@name)`)) if err != nil { log.Fatal(err) } defer plan.Close() names := []string{"alice", "bob", "carol"} for _, name := range names { session, err := plan.NewSession(ctx, ferret.WithSessionParam("name", name), ) if err != nil { log.Fatal(err) } output, err := session.Run(ctx) session.Close() if err != nil { log.Fatal(err) } fmt.Println(string(output.Content)) } // "ALICE" // "BOB" // "CAROL"

The plan manages an internal pool of virtual machines. Sessions borrow a VM from the pool and return it on close, so creating many sessions from the same plan is efficient.

Passing parameters

Parameters let the host application inject values into a query at runtime. In FQL, parameters are referenced with the @ prefix.

Engine-level parameters apply to every session:

example.go
read-only
engine, err := ferret.New( ferret.WithParam("base_url", "https://api.example.com"), )

Session-level parameters override engine defaults for a single execution:

example.go
read-only
session, err := plan.NewSession(ctx, ferret.WithSessionParam("user_id", 42), ferret.WithSessionParam("base_url", "https://staging.example.com"), )

You can inspect which parameters a compiled query declares:

example.go
read-only
params := plan.Params() fmt.Println(params) // [base_url user_id]

See Parameters for the full parameter API.

Handling errors

Ferret returns standard Go errors. Compilation errors include source location information:

example.go
read-only
_, err := engine.Compile(ctx, source.New("bad.fql", `return @`)) if err != nil { fmt.Println(err) // compilation error with line and column }

Runtime errors from query execution are returned by session.Run:

example.go
read-only
output, err := session.Run(ctx) if err != nil { // handle runtime error }

Context cancellation and timeouts work as expected:

example.go
read-only
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() output, err := session.Run(ctx) if err != nil { // may be context.DeadlineExceeded }

The VM observes cancellation at structural execution boundaries rather than polling every native operation. Blocking host functions, iterators, queries, streams, and other context-aware capabilities receive this same context and must observe it while they retain control. Cancellation and deadline errors propagate to the caller and cannot be suppressed by FQL error recovery.

Next steps