我有一个结构体Person,它的字段AccessMode类型为 uint
. 在 Postgres 数据库中,AccessMode 的数据类型是 char(8)
.我为AccessMode写了一个自定义的Scan函数,它实现了Scanner Interface.在Scan函数中,它是作为一个函数接收的。uint8
ASCII字符串的分片表示。当AccessMode的数据类型变更为 varchar(8)
在数据库中,它是作为一个 string
在扫描功能中。以下是代码
type Access uint
type Person struct {
AccessMode Access
}
func (a *Access) Scan(val interface{}) error {
if bb, ok := val.([]byte); ok {
return a.UnmarshalText(bb)
}
return errors.New("scan failed: data is not a byte slice")
}
为什么在扫描函数中,如果是varchar,则以字符串的形式接收,如果是char数据类型,则以uint slice的形式接收?
这取决于你使用的驱动程序,为了避免出现这样的问题,你需要查阅驱动程序的文档。例如 github.com/lib/pq
驱动程序在其 文件.
你会注意到,在上面的 lib/pq
声称返回的值为 char
类型为 string
虽说是这样,但是 似乎 像不像。我的意思是说,在postgres中,有一个叫 char
类型,然后是 "char"
型,以及 lib/pq
上文中的是指后者。
如果可能,你应该避免使用 char
和 varchar
而改用 text
.
当你声明一个列的类型为 char
或 char(n)
,该列的实际类型将是 bpchar
(空白填充、固定长度的字符类型),这不是由 lib/pq
(尽管它可能应该是)。
当你声明一个列的类型为 "char"
,该列的实际类型将是 "char"
内用字型,这是由 lib/pq
并返回为 string
.
为了在这种特殊情况下屏蔽自己,你可以使用类型开关。
func (a *Access) Scan(src interface{}) error {
switch val := src.([]byte) {
case []byte:
return a.UnmarshalText(val)
case string:
return a.UnmarshalText([]byte(val))
}
return errors.New("scan failed: data is not a byte slice")
}