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

Implement database/sql.Scanner interface

王林
Release: 2024-02-10 13:30:08
forward
628 people have browsed it

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)
}
Copy after login

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
}
Copy after login

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)
}
Copy after login

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)
}
Copy after login

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)
}
Copy after login

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!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template