liveBook · Manning

Driver.Valuer

As explained in Go by Example

driver.Valuer is a Go interface implemented by types that convert themselves into values accepted by a database driver.

driver.Valuer is a Go interface for transforming a value before database/sql sends it through a database driver. Its single method, Value, returns a driver.Value and an error. section 10.3

Use Valuer when a database representation should differ from the application representation:

  • Define Value() (driver.Value, error) on a custom type. section 10.3
  • Return the encoded or otherwise transformed representation from Value. section 10.3.2
  • Pass the custom value to ExecContext or another database operation; database/sql invokes Value automatically. section 10.3.3

Encoding a URL before storage

A custom base64String type implements Value by encoding its contents with base64.StdEncoding.EncodeToString. Shorten passes base64String(lnk.URL) to ExecContext, so the database receives the encoded string while the application keeps using a URL-shaped value. Pairing Valuer with sql.Scanner lets Resolve decode the stored string when it scans into a *base64String. section 10.3.2 section 10.3.3

Listing 10.11 Valuer and Scanner (link/sqlite/shortener.go)
package sqlite

import (
    "database/sql/driver"
    "encoding/base64"
    . . .
)

type base64String string

// Value implements the driver.Valuer interface.
func (bs base64String) Value() (driver.Value, error) {
    return base64.StdEncoding.EncodeToString([]byte(bs)), nil
}

// Scan implements the sql.Scanner interface.
func (bs *base64String) Scan(src any) error {
    ss, ok := src.(string)  #1
    if !ok {
        return fmt.Errorf("decoding: %q is %T, not string", ss, src)
    }
    dst, err := base64.StdEncoding.DecodeString(ss)
    if err != nil {
        return fmt.Errorf("decoding %q: %w", ss, err)
    }
    *bs = base64String(dst) #2
    return nil
}

// String implements the fmt.Stringer interface.
func (bs base64String) String() string {
    return string(bs)
}

Inspect the complete base64String implementation, including the Value method and its paired Scan method. section 10.3.2

How Go by Example covers it

How deep it goes
Defines one method and demonstrates automatic encoding, while deferring database-driver-specific behavior to consumers.
Examples
Encodes shortened URLs as Base64 strings and points to UUID storage as binary data.
What it assumes
Builds on Go interfaces and database/sql operations, while demonstrating the custom transformation pattern directly.
What you can do after
Build it from scratch by defining Value and passing the custom type to database operations.
How it connects
Connects database/sql, database/sql/driver, sql.Scanner, custom types, and Base64 encoding.

This explainer was generated by Manning's knowledge graph from the text of Go by Example. The section links point to the parts of the book it draws on.