Home  >  Article  >  Backend Development  >  Implement database/sql.Scanner interface

Implement database/sql.Scanner interface

王林
王林forward
2024-02-10 13:30:08578browse

Implement database/sql.Scanner interface

php editor Yuzai will introduce to you how to implement the database/sql.Scanner interface in this article. In the Go language, the database/sql package is the core package used to operate relational databases. The Scanner interface is used to scan the values ​​in the database query results into Go language variables. By implementing the Scanner interface, we can customize the conversion of the values ​​in the database query results into the type we want. This article will explain in detail how to implement the Scanner interface to help readers better understand and apply database operations in the Go language.

Question content

How to implement the database/sql.Scanner interface?

In this query, there are 3 fields in the SELECT clause:

  • idsmallint unsigned
  • is_suspended tinyint unsigned
  • name varchar

In database/sql, the data type of the 3 columns is:

  • int64
  • int64
  • []uint8

This works for []interface{}, but would like to implement each column type directly into the database/sql.Scanner interface

cols    := make([]interface{}, 3)
ptr     := make([]interface{}, 3)

for i, _ := range cols {
    ptr[i] = &cols[i]
}

if err := rows.Scan(ptr...); err != nil {
    fmt.Println("err:", err)
}

// pair column data with column name
res := map[string]any
for i, name := range res_cols {
    res[name] = *ptr[i].(*any)
    
    fmt.Printf("Type: %T %s\n", res[name], name)
}

Things I tried to do but couldn't really make it work

type

type Type_int int

func (t *Type_int) Scan(value interface{}) error {
    switch value := value.(type) {
    case int64:
        *t = Type_int(value)
    default:
        return fmt.Errorf("Invalid database type: %T %v", value, value)
    }
    return nil
}

type Type_string string

func (t *Type_string) Scan(value interface{}) error {
    switch value := value.(type) {
    case []uint8:
        *t = Type_string(value)
    default:
        return fmt.Errorf("Invalid database type: %T %v", value, value)
    }
    return nil
}

Code

ptr     := make([]interface{}, 3)

cols    := []interface{}{
    Type_int,
    Type_int,
    Type_string,
}

for i, _ := range cols {
    ptr[i] = &cols[i]
}

if err := rows.Scan(ptr...); err != nil {
    fmt.Println("err:", err)
}

// pair column data with column name
res := map[string]any
for i, name := range res_cols {
    res[name] = *ptr[i].(*any)
    
    fmt.Printf("Type: %T %s\n", res[name], name)
}

Workaround

Initialize ptr with a pointer to a value of the given type.

var c1 Type_int
var c2 Type_int
var c3 Type_string
ptr := []any{&c1, &c2, &c3}
if err := rows.Scan(ptr...); err != nil {
    fmt.Println("err:", err)
}

ptr The slice does not provide any value in the above snippet. The code can be simplified to:

var c1 Type_int
var c2 Type_int
var c3 Type_string
if err := rows.Scan(&c1, &c2, &c3); err != nil {
    fmt.Println("err:", err)
}

The above is the detailed content of Implement database/sql.Scanner interface. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete