返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

scan & null

发布于 2024-10-12 19:15:52 字数 2714 浏览 0 评论 0 收藏 0

Scan 相关的取值和转换操作。

RawBytes

接收任何数据的字节数组,可用于未知类型字段。

  • 引用底层驱动( sql/driver )管理的内存。
  • 有效期在下次 NextScanClose 调用前。
  • 不能用于 Row.Scan
type RawBytes []byte
for rows.Next() {
	var name sql.RawBytes
    rows.Scan(&name)
}

Null

标准库专门为常用类型提供了空值类型。

空值(Null、NULL)是结构化查询语言中使用的特殊标记,是关联式资料库中对数据属性未知或缺失的一种标识,用于指示数据库中不存在数据值。—— 维基百科

type NullString struct {
	String string
	Valid  bool // Valid is true if String is not NULL
}

type NullInt64 struct {
	Int64 int64
	Valid bool // Valid is true if Int64 is not NULL
}
var name sql.NullString

rows.Scan(&name)

if name.Valid {
	fmt.Println(name.String)
}

Valuer, Scanner

基于两个接口实现 Scan 自定义编码和解码操作。比如压缩、加密等。
空值类型就是实现了这两个接口。

  • Scanner :对返回的数据进行处理。
  • Valuer :对准备写入的数据进行处理。
type Scanner interface {
	// Scan assigns a value from a database driver.
	//
	// The src value will be of one of the following types:
	//
	//    int64
	//    float64
	//    bool
	//    []byte
	//    string
	//    time.Time
	//    nil - for NULL values
	//
	// An error should be returned if the value cannot be stored
	// without loss of information.
	//
	// Reference types such as []byte are only valid until the next 
    // call to Scan and should not be retained. Their underlying memory 
    // is owned by the driver. If retention is necessary, copy their 
    // values before the next call to Scan.
	Scan(src any) error
}
type Valuer interface {
	// Value returns a driver Value.
	// Value must not panic.
	Value() (Value, error)
}

示例:

package main

import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"fmt"

	_ "github.com/mattn/go-sqlite3"
)

// -------------------------------------------

const prefix = "**"
type X string

func (x X) Value() (driver.Value, error) {
	return string(prefix + x), nil
}

func (x *X) Scan(v interface{}) error {
	if n, ok := v.(string); ok {
		*x = X(n[len(prefix):])
		return nil
	}

	return errors.New("invalid")
}

// -------------------------------------------

func main() {
	db, _ := sql.Open("sqlite3", "./test.db")
	defer db.Close()

	id := 203
	qs := []string {
		"INSERT INTO user (id, name) VALUES (?, ?)",
		"SELECT name FROM user WHERE id = ?",
	}

	db.Exec(qs[0], id, X("a"))

	var name string
	var namex X

	db.QueryRow(qs[1], id).Scan(&name)
	db.QueryRow(qs[1], id).Scan(&namex)

	fmt.Println(name, namex)   // **a  a
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文