Go driver

Go logo

This section describes Fauna’s open source Go driver, which provides the resources required to interact with Fauna.

Current stable version

4.3.0

Repository

Supported Go versions

Currently, the driver is tested on the following Go versions:

  • 1.13

  • 1.14

  • 1.15

  • 1.16

Install

To get the latest version run:

go get github.com/fauna/faunadb-go/v4/faunadb

Please note that the driver undergoes breaking changes from time to time. It is recommended to use one of the following methods instead:

Usage

Here is an example demonstrating how to use the Go driver to execute a simple query on Fauna:

Use the correct endpoint value for your database’s Region Group.
package main

import (
    "fmt"
    f "github.com/fauna/faunadb-go/v4/faunadb"
)

type User struct {
    Name string `fauna:"name"`
}

func main() {
    client := f.NewFaunaClient(
        "YOUR_FAUNA_SECRET",
        f.Endpoint("http://localhost:8443/")
        // NOTE: use the correct endpoint for your database's Region Group.
    )

    res, err := client.Query(f.Get(f.Ref(f.Collection("user"), "42")))
    if err != nil {
        panic(err)
    }

    var user User

    if err := res.At(f.ObjKey("data")).Get(&user); err != nil {
        panic(err)
    }

    fmt.Println(user)
}

See Connections for more details on creating client connections. See Region Groups for more details on domain names for Region Groups.

Query timeout

Your code can configure the client to handle timeouts in two different ways:

  1. by adding a call to QueryTimeoutMS to the options block when instantiating the client, or

  2. by adding a call to TimeoutMS as the second parameter to the .Query method.

When you provide a query timeout, the server waits for the specified period before timing out, if it has yet to complete the current query. Once the period has elapsed, the query fails and the server responds with an error.

Both timeouts are expressed in milliseconds.

For example:

// Specify a query timeout during client instantiation
client := f.NewFaunaClient(
	"secret",
	f.QueryTimeoutMS(1))
// Specify a query timeout per query
result, err := client.Query(
	 f.Paginate(f.Collections()),
	 f.TimeoutMS(1))

The value used in the TimeoutMS call passed to .Query() takes precedence over any value used in the QueryTimeoutMS call during client instantiation.

omitempty usage

When marshalling JSON data into Fauna queries, or out of Fauna responses, the omitempty tag can help deal with variability in JSON documents:

package main

import f "github.com/fauna/faunadb-go/v4/faunadb"

func main() {
	secret := "YOUR_FAUNA_SECRET"
	client = f.NewFaunaClient(secret)
	var ref f.RefV
	value, err := client.Query(f.Get(&ref))
	if err != nil {
		panic(err)
	}

	type OmitStruct struct {
		Name           string      `fauna:"name,omitempty"`
		Age            int         `fauna:"age,omitempty"`
		Payment        float64     `fauna:"payment,omitempty"`
		AgePointer     *int        `fauna:"agePointer,omitempty"`
		PaymentPointer *float64    `fauna:"paymentPointer,omitempty"`
	}

	_, err := client.Query(
		f.Create(f.Collection("categories"), f.Obj{"data": OmitStruct{Name: "John", Age: 0}}))
	if err != nil {
		panic(err)
	}
}

When you run this example (be sure to replace YOUR_FAUNA_SECRET with your actual secret), the result should exclude empty/zero fields:

{
  "ref": Ref(Collection("categories"), "295143889346494983"),
  "ts": 1617729997710000,
  "data": {
    "name": "John"
  }
}

Tracing

A trace uniquely identifies a transaction flow. In distributed scenarios, a traceparent propagates a contextual identifier, which lets you associate logs from disparate services that participate in the application. The traceparent request header represents a request in a tracing system using a common format. See traceparent.

Fauna supports distributed tracing by allowing you to apply a traceparent header to individual queries. The traceparent request header format is similar to this example:
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01.

Use the identifier in the query response in subsequent queries. If the Fauna query logic is not the main application, you should use the identifier provided by that application and follow the recommended processing model for mutating the identifier.

If you don’t include a traceparent identifier, one is generated for you and attached to the query response.

Tags

You can tag individual queries with identifiers that can be used to associate operations by using the x-fauna-tags header tag.

  • Tags and associated values can be alphanumeric strings and include the underscore (_) character.

  • Tag names can be up to 40 characters, and tag values can be up to 80 characters.

  • You can have up to 25 tags per query.

A query fails with a 400 status code if the tag is invalid.

HTTP/2 support

The Go driver uses HTTP/2 by default. To use HTTP/1.x, provide a custom HTTP client to FaunaClient:

package main

import (
  f "github.com/fauna/faunadb-go/v4/faunadb"
  "net/http"
)

func main() {
	secret := ""
	customHttpClient := http.Client{}
	client = f.NewFaunaClient(secret, f.HTTP(&customHttpClient))
}

Event streaming

This section demonstrates how to subscribe to change events.

There are two kinds of event streaming:

The code required to subscribe to each type is very similar. The primary difference is the type of Reference involved in the subscription, and the kinds of events that are included in the stream.

There is a cost in compute operations to hold a stream open, or to repeatedly start a stream that fails.

See Billing for details.

Document streaming

The following example subscribes to change events for a specific document:

	client := f.NewFaunaClient(secret, f.Endpoint(endpoint))

	// Define a reference to the document that we want to stream
	// Note that the Scores collection must already exist
	var ref = f.Ref(f.Collection("Scores"), "1")

	// Setup the stream subscriber
	var subscription f.StreamSubscription
	subscription = client.Stream(ref)
	err := subscription.Start()
	if err != nil {
		fmt.Println(err)
		panic("Panic")
	}

	// Handle stream events
	for event := range subscription.StreamEvents() {
		fmt.Println(event)
		switch event.Type() {
			case f.StartEventT:
				// Do something with the start event

			case f.HistoryRewriteEventT:
				// Do something with history rewrite events

			case f.VersionEventT:
				// Do something with version events

			case f.ErrorEventT:
				// Handle stream errors
				// In this case, we close the stream
				subscription.Close()
		}
	}

Before you run the example:

  1. Set the FAUNADB_SECRET environment variable, and optionally the FAUNADB_ENDPOINT environment variable (if you are using Region Groups or Fauna Dev).

  2. The collection Scores must exist.

Once the example is running, you can use the Fauna Dashboard, or another client application, to create or update the target document and watch the events arrive as the changes are made.

For example, if the document does not yet exist, you could run this query in the Fauna Dashboard Shell:

Create(Ref(Collection("Scores"), "1"), { data: { scores: [1, 2, 3] }})

Once the document exists, you could run this query:

Update(Ref(Collection("Scores"), "1"), { data: { scores: [5, 2, 3] }})

The streaming example waits indefinitely for events. Use Ctrl+C to terminate the program.

Set streaming

The following example subscribes to change events for a set:

	client := f.NewFaunaClient(secret, f.Endpoint(endpoint))

	// Define the reference to the target set
	var ref = f.Documents(f.Collection("Scores"))

	// Define the stream fields to include
	var streamOptions = f.Fields("action", "document", "index")

	// Setup the stream subscriber
	var subscription f.StreamSubscription
	subscription = client.Stream(ref, streamOptions)
	err := subscription.Start()
	if err != nil {
		fmt.Println(err)
		panic("Panic")
	}

	// Handle stream events
	for event := range subscription.StreamEvents() {
		fmt.Println(event)
		switch event.Type() {
			case f.StartEventT:
				// Do something with the start event

			case f.SetEventT:
				// Do something with set events

			case f.ErrorEventT:
				// Handle stream errors
				// In this case, we close the stream
				subscription.Close()
		}
	}

Before you run the example:

  1. Set the FAUNADB_SECRET environment variable, and optionally the FAUNADB_ENDPOINT environment variable (if you are using Region Groups or Fauna Dev).

  2. The collection Scores must exist.

Once the example is running, you can use the Fauna Dashboard, or another client application, to add or delete documents in the "Scores" collection and watch the events arrive as the changes are made. For example, you could run this query in the Fauna Dashboard's Shell:

Create(Collection("Scores"), { data: { scores: [5, 6, 7] }})

The streaming example waits indefinitely for events. Use Ctrl+C to terminate the program.

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!