Package edgedb is the official Go EdgeDB driver. https://www.edgedb.com

Typical usage looks like this:

Copy
package main

import (
    "context"
    "log"

    "github.com/edgedb/edgedb-go"
)

func main() {
    ctx := context.Background()
    client, err := edgedb.CreateClient(ctx, edgedb.Options{})
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    var (
        age   int64 = 21
        users []struct {
            ID   edgedb.UUID `edgedb:"id"`
            Name string      `edgedb:"name"`
        }
    )

    query := "SELECT User{name} FILTER .age = <int64>$0"
    err = client.Query(ctx, query, &users, age)
    ...
}

You can also connect to a database using a DSN:

Copy
url := "edgedb://edgedb@localhost/edgedb"
client, err := edgedb.CreateClientDSN(ctx, url, opts)

Or you can use Option fields.

Copy
opts := edgedb.Options{
    Database:    "edgedb",
    User:        "edgedb",
    Concurrency: 4,
}

client, err := edgedb.CreateClient(ctx, opts)

edgedb never returns underlying errors directly. If you are checking for things like context expiration use errors.Is() or errors.As().

Copy
err := client.Query(...)
if errors.Is(err, context.Canceled) { ... }

Most errors returned by the edgedb package will satisfy the edgedb.Error interface which has methods for introspecting.

Copy
err := client.Query(...)

var edbErr edgedb.Error
if errors.As(err, &edbErr) && edbErr.Category(edgedb.NoDataError){
    ...
}

The following list shows the marshal/unmarshal mapping between EdgeDB types and go types:

Copy
EdgeDB                   Go
---------                ---------
Set                      []anytype
array<anytype>           []anytype
tuple                    struct
named tuple              struct
Object                   struct
bool                     bool, edgedb.OptionalBool
bytes                    []byte, edgedb.OptionalBytes
str                      string, edgedb.OptionalStr
anyenum                  string, edgedb.OptionalStr
datetime                 time.Time, edgedb.OptionalDateTime
cal::local_datetime      edgedb.LocalDateTime,
                         edgedb.OptionalLocalDateTime
cal::local_date          edgedb.LocalDate, edgedb.OptionalLocalDate
cal::local_time          edgedb.LocalTime, edgedb.OptionalLocalTime
duration                 time.Duration, edgedb.OptionalDuration
cal::relative_duraation  edgedb.RelativeDuration,
                         edgedb.OptionalRelativeDuration
float32                  float32, edgedb.OptionalFloat32
float64                  float64, edgedb.OptionalFloat64
int16                    int16, edgedb.OptionalFloat16
int32                    int32, edgedb.OptionalInt16
int64                    int64, edgedb.OptionalInt64
uuid                     edgedb.UUID, edgedb.OptionalUUID
json                     []byte, edgedb.OptionalBytes
bigint                   *big.Int, edgedb.OptionalBigInt

decimal                  user defined (see Custom Marshalers)

Shape fields that are not required must use optional types for receiving query results. The edgedb.Optional struct can be embedded to make structs optional.

Interfaces for user defined marshaler/unmarshalers are documented in the internal/marshal package.

Copy
package edgedb_test

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/edgedb/edgedb-go"
)

type User struct {
    ID   edgedb.UUID `edgedb:"id"`
    Name string      `edgedb:"name"`
    DOB  time.Time   `edgedb:"dob"`
}

func Example() {
    opts := edgedb.Options{Concurrency: 4}
    ctx := context.Background()
    db, err := edgedb.CreateClientDSN(ctx, "edgedb://edgedb@localhost/test", opts)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // create a user object type.
    err = db.Execute(ctx, `
        CREATE TYPE User {
            CREATE REQUIRED PROPERTY name -> str;
            CREATE PROPERTY dob -> datetime;
        }
    `)
    if err != nil {
        log.Fatal(err)
    }

    // Insert a new user.
    var inserted struct{ id edgedb.UUID }
    err = db.QuerySingle(ctx, `
        INSERT User {
            name := <str>$0,
            dob := <datetime>$1
        }
    `, &inserted, "Bob", time.Date(1984, 3, 1, 0, 0, 0, 0, time.UTC))
    if err != nil {
        log.Fatal(err)
    }

    // Select users.
    var users []User
    args := map[string]interface{}{"name": "Bob"}
    query := "SELECT User {name, dob} FILTER .name = <str>$name"
    err = db.Query(ctx, query, &users, args)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(users)
}
Light
Dark
System