Package edgedb is the official Go EdgeDB driver. https://edgedb.com
Typical usage looks like this:
import (
"context"
"log"
"github.com/edgedb/edgedb-go"
)
opts := edgedb.Options{
MinConns: 1,
MaxConns: 4,
}
func main() {
ctx := context.Background()
pool, err := edgedb.ConnectDSN(ctx, "my_instance", opts)
if err != nil {
log.Fatal(err)
}
defer pool.Close()
var (
age int64 = 21
users []struct{
ID edgedb.UUID `edgedb:"id"`
Name string `edgedb:"name"`
}
)
query := "SELECT User{name} WHERE .age = <int64>$0"
err = pool.Query(ctx, query, &users, age)
...
}
You can also connect to a database using a DSN:
url := "edgedb://edgedb@localhost/edgedb"
pool, err := edgedb.ConnectDSN(ctx, url, opts)
Or you can use Option fields.
opts := edgedb.Options{
Database: "edgedb",
User: "edgedb",
MinConns: 1,
MaxConns: 4,
}
pool, err := edgedb.Connect(ctx, opts)
Most use cases will benefit from the concurrency safe pool implementation returned from Connect() and ConnectDSN(). Pool.Acquire(), ConnectOne() and ConnectOneDSN() will give you access to a single connection.
edgedb never returns underlying errors directly. If you are checking for things like context expiration use errors.Is() or errors.As().
err := pool.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.
err := pool.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:
EdgeDB Go
--------- ---------
Set []anytype
array<anytype> []anytype
tuple struct
named tuple struct
Object struct
bool bool
bytes []byte
str string
anyenum string
datetime time.Time
cal::local_datetime edgedb.LocalDateTime
cal::local_date edgedb.LocalDate
cal::local_time edgedb.LocalTime
duration time.Duration
float32 float32
float64 float64
int16 int16
int32 int32
int64 int64
uuid edgedb.UUID
json []byte
bigint *big.Int
decimal user defined (see Custom Codecs)
User defined marshaler/unmarshalers can be defined for any scalar EdgeDB type except arrays. The marshaler interfaces are documented in the internal/codecs package.
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{
MinConns: 1,
MaxConns: 4,
}
ctx := context.Background()
db, err := edgedb.ConnectDSN(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.QueryOne(ctx, `
INSERT User {
name := <str>$1,
dob := <datetime>$2
}
`, 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)
}