> ## Documentation Index
> Fetch the complete documentation index at: https://bunnynet-cb9733c2-support-migration.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Go

> Get started with Bunny Database and Go using the libSQL client

In this Go quickstart you will learn how to:

* Retrieve database credentials
* Install the libSQL client
* Connect to a remote Bunny Database
* Execute a query using SQL

## Quickstart

<Steps>
  <Step title="Retrieve database credentials">
    You will need an existing database to continue. If you don't have one, [create one](/database/quickstart).

    Navigate to **Dashboard > Edge Platform > Database > \[Select Database] > Access** to find your database URL and generate an access token.

    <Info>
      You should store these as environment variables to keep them secure.
    </Info>
  </Step>

  <Step title="Install libsql-client-go">
    Install the libSQL client package:

    ```bash theme={null}
    go get github.com/tursodatabase/libsql-client-go/libsql
    ```
  </Step>

  <Step title="Initialize a new client">
    Create a database connection with your database URL and auth token:

    ```go theme={null}
    package main

    import (
    	"database/sql"
    	"fmt"
    	"os"

    	_ "github.com/tursodatabase/libsql-client-go/libsql"
    )

    func main() {
    	url := fmt.Sprintf("%s?authToken=%s",
    		os.Getenv("BUNNY_DATABASE_URL"),
    		os.Getenv("BUNNY_DATABASE_AUTH_TOKEN"),
    	)

    	db, err := sql.Open("libsql", url)
    	if err != nil {
    		fmt.Fprintf(os.Stderr, "failed to open db %s: %s", url, err)
    		os.Exit(1)
    	}
    	defer db.Close()
    }
    ```
  </Step>

  <Step title="Execute a query using SQL">
    You can execute a SQL query against your database using `Query()` for reads or `Exec()` for writes:

    ```go theme={null}
    rows, err := db.Query("SELECT * FROM users")
    if err != nil {
    	fmt.Fprintf(os.Stderr, "failed to execute query: %v\n", err)
    	os.Exit(1)
    }
    defer rows.Close()

    for rows.Next() {
    	var id int
    	var name string
    	if err := rows.Scan(&id, &name); err != nil {
    		fmt.Fprintf(os.Stderr, "failed to scan row: %v\n", err)
    		os.Exit(1)
    	}
    	fmt.Printf("id: %d, name: %s\n", id, name)
    }

    if err := rows.Err(); err != nil {
    	fmt.Fprintf(os.Stderr, "error during iteration: %v\n", err)
    	os.Exit(1)
    }
    ```

    If you need to use placeholders for values, you can do that:

    <CodeGroup>
      ```go Positional theme={null}
      rows, err := db.Query("SELECT * FROM users WHERE id = ?", 1)
      ```

      ```go Named theme={null}
      rows, err := db.Query("SELECT * FROM users WHERE id = :id", sql.Named("id", 1))
      ```
    </CodeGroup>
  </Step>
</Steps>

## Placeholders

libSQL supports the use of positional and named placeholders within SQL statements:

<CodeGroup>
  ```go Positional theme={null}
  rows, err := db.Query("SELECT * FROM users WHERE id = ?", 1)
  ```

  ```go Named theme={null}
  rows, err := db.Query("SELECT * FROM users WHERE id = :id", sql.Named("id", 1))
  ```
</CodeGroup>

<Info>
  libSQL supports the same named placeholder characters as SQLite — `:`, `@` and
  `$`.
</Info>

## Executing Writes

Use `Exec()` for INSERT, UPDATE, and DELETE statements:

```go theme={null}
result, err := db.Exec("INSERT INTO users (name) VALUES (?)", "Kit")
if err != nil {
	fmt.Fprintf(os.Stderr, "failed to insert: %v\n", err)
	os.Exit(1)
}

rowsAffected, _ := result.RowsAffected()
lastInsertId, _ := result.LastInsertId()

fmt.Printf("rows affected: %d, last insert id: %d\n", rowsAffected, lastInsertId)
```

## Transactions

You can use transactions to execute multiple statements atomically:

```go theme={null}
tx, err := db.Begin()
if err != nil {
	fmt.Fprintf(os.Stderr, "failed to begin transaction: %v\n", err)
	os.Exit(1)
}

_, err = tx.Exec("INSERT INTO users (name) VALUES (?)", "Kit")
if err != nil {
	tx.Rollback()
	fmt.Fprintf(os.Stderr, "failed to insert: %v\n", err)
	os.Exit(1)
}

_, err = tx.Exec("INSERT INTO users (name) VALUES (?)", "Sam")
if err != nil {
	tx.Rollback()
	fmt.Fprintf(os.Stderr, "failed to insert: %v\n", err)
	os.Exit(1)
}

if err := tx.Commit(); err != nil {
	fmt.Fprintf(os.Stderr, "failed to commit: %v\n", err)
	os.Exit(1)
}
```

## Prepared Statements

For repeated queries, you can use prepared statements for better performance:

```go theme={null}
stmt, err := db.Prepare("SELECT * FROM users WHERE id = ?")
if err != nil {
	fmt.Fprintf(os.Stderr, "failed to prepare statement: %v\n", err)
	os.Exit(1)
}
defer stmt.Close()

rows, err := stmt.Query(1)
if err != nil {
	fmt.Fprintf(os.Stderr, "failed to execute query: %v\n", err)
	os.Exit(1)
}
defer rows.Close()
```

## Context Support

The libSQL client supports Go's context for timeout and cancellation:

```go theme={null}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

rows, err := db.QueryContext(ctx, "SELECT * FROM users")
if err != nil {
	fmt.Fprintf(os.Stderr, "failed to execute query: %v\n", err)
	os.Exit(1)
}
defer rows.Close()
```
