关于database/sql.Scanner接口实现的两处技术疑问
关于
database/sql.Scanner实现的疑问解答 代码示例
type Foo int // Scan implements the database/sql.Scanner interface func (f *Foo) Scan(value interface{}) error { switch value := value.(type) { case int64: *f = Foo(value) default: return fmt.Errorf("Invalid database type: %T %v", value, value) } return nil }
问题1:Scan方法返回error类型,为何能返回fmt.Errorf(...)?
fmt.Errorf的返回值本身就属于error类型,完全符合Scan方法的返回要求。Go中的error是一个接口,只要实现了Error() string方法的类型都属于error类型,而fmt.Errorf返回的*errors.errorString结构体正好实现了这个方法,所以返回它是完全合法的。
问题2:关于*f = Foo(value)及rows.Scan()的相关疑问
*f = Foo(value)的作用:将数据库返回的int64值转换成Foo类型,然后赋值给调用该Scan方法的指针所指向的Foo变量。比如你声明了var foo Foo,调用rows.Scan(&foo)时,这个赋值操作会把数据库中的数值存入foo变量。- 传入
rows.Scan()时会调用Foo.Scan()吗:会的。database/sql包在处理Scan参数时,会检查参数是否实现了Scanner接口(即是否拥有Scan(value interface{}) error方法),而*Foo正好实现了这个接口,所以会自动调用你编写的Scan方法。 - 类型为
int64时会执行Foo(value)转换吗:是的。Foo是基于int的自定义类型,int64到Foo的转换是合法的类型转换(只要数值在当前系统int的范围内),这一步会把int64类型的value转换为Foo类型,再赋值给*f。
内容的提问来源于stack exchange,提问作者clarkk
相关产品推荐
相关产品推荐

