英文:
Error "value of type []uint8 is not assignable to type []string" when scanning a DB row
问题
我正在使用PostgreSQL作为后端数据库。
尝试扫描一个名为languagespoken
的字段,它是一个文本数组。
var user userprofile
row := core.db.QueryRow(
"SELECT languagespoken FROM \"user\" WHERE id = $1",
userId,
)
err := row.Scan(&user.Languages)
if err != nil {
return user, err
}
我的结构如下:
type userprofile struct {
Languages []string `json:"languages"`
}
但是出现了以下错误:
2014/06/30 15:27:17 PANIC: reflect.Set: **类型为 []uint8 的值无法赋值给类型为 []string 的变量**
/usr/lib/go/src/pkg/reflect/value.go:2198 (0x56c152)
Value.assignTo: panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
/usr/lib/go/src/pkg/reflect/value.go:1385 (0x56966b)
Value.Set: x = x.assignTo("reflect.Set", v.typ, target)
/usr/lib/go/src/pkg/database/sql/convert.go:215 (0x492d70)
convertAssign: dv.Set(sv)
/usr/lib/go/src/pkg/database/sql/sql.go:1562 (0x49c0e5)
(*Rows).Scan: err := convertAssign(dest[i], sv)
/usr/lib/go/src/pkg/database/sql/sql.go:1630 (0x49c560)
(*Row).Scan: err := r.rows.Scan(dest...)
/home/ceresti/source/gocode/src/ceresti.kilnhg.com/ceresti/server/app/databaseapi.go:144 (0x402478)
(*coreStruct).GetUserProfile: err := row.Scan(&user.Languages)
/home/ceresti/source/gocode/src/ceresti.kilnhg.com/ceresti/server/app/restfulapi.go:327 (0x40a63c)
Getuserprofile: userprofileStruct, err := core.GetUserProfile(userId)
/usr/lib/go/src/pkg/runtime/asm_amd64.s:340 (0x4309c2)
请告诉我如何解决这个问题。
英文:
I am using postgresql as my backend database.
Tried to scan a field languagespoken
which is an array of text
var user userprofile
row := core.db.QueryRow(
"SELECT languagespoken FROM \"user\" WHERE id = $1",
userId,
)
err := row.Scan(&user.Languages)
if err != nil {
return user, err
}
My structure looks like this
type userprofile struct {
Languages []string `json:languages`
}
But getting the error
2014/06/30 15:27:17 PANIC: reflect.Set: **value of type []uint8 is not assignable to type []string**
/usr/lib/go/src/pkg/reflect/value.go:2198 (0x56c152)
Value.assignTo: panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String())
/usr/lib/go/src/pkg/reflect/value.go:1385 (0x56966b)
Value.Set: x = x.assignTo("reflect.Set", v.typ, target)
/usr/lib/go/src/pkg/database/sql/convert.go:215 (0x492d70)
convertAssign: dv.Set(sv)
/usr/lib/go/src/pkg/database/sql/sql.go:1562 (0x49c0e5)
(*Rows).Scan: err := convertAssign(dest[i], sv)
/usr/lib/go/src/pkg/database/sql/sql.go:1630 (0x49c560)
(*Row).Scan: err := r.rows.Scan(dest...)
/home/ceresti/source/gocode/src/ceresti.kilnhg.com/ceresti/server/app/databaseapi.go:144 (0x402478)
(*coreStruct).GetUserProfile: err := row.Scan(&user.Languages)
/home/ceresti/source/gocode/src/ceresti.kilnhg.com/ceresti/server/app/restfulapi.go:327 (0x40a63c)
Getuserprofile: userprofileStruct, err := core.GetUserProfile(userId)
/usr/lib/go/src/pkg/runtime/asm_amd64.s:340 (0x4309c2)
Please let me know how to resolve this issue.
答案1
得分: 5
并非所有的SQL数据库都指定了数组类型(例如,sqlite3)。Go语言不直接支持任何SQL实现,但它提供了一个与实现无关的接口,第三方驱动程序可以基于此接口编写。Go语言不对驱动程序支持的类型施加任何限制,所以如果某个类型不兼容,很可能是驱动程序的问题。
简而言之:尝试将其作为字符串获取
// 如果 `string` 不起作用,尝试 `[]uint8` 或 `[]byte`,然后根据需要将输出转换为字符串
var languages string
if err := row.Scan(&languages); err != nil {
// 处理错误
}
// 根据字符串的编码方式,这可能有效或无效
// 更新:根据你所说,你的列表以以下形式编码:
// `{elem1, elem2, elem3}`,我们将忽略第一个和最后一个字符,并在“,”上进行拆分
user.Languages = strings.Split(languages[1:len(languages)-1], ", ")
英文:
Not all sql databases specify array types (e.g., sqlite3). Go doesn't support any sql implementations directly, but it supplies an implementation-agnostic interface (in the generic sense of the word) for which third-party drivers may be written. Go doesn't impose any limitations on which types its drivers may support, so if a type doesn't cooperate, it's probably the fault of the driver.
TL;DR: Try getting it as a string
// if `string` doesn't work, try `[]uint8` or `[]byte` and then convert
// that output to a string if necessary
var languages string
if err := row.Scan(&languages); err != nil {
// handle error
}
// depending on how the string is encoded, this may or may not work
// Update: since you say your list is encoded in the form:
// `{elem1, elem2, elem3}`, we'll simply ignore the first and last
// characters and split on ", "
user.Languages = strings.Split(languages[1:len(languages)-1], ", ")
答案2
得分: 2
看起来你正在尝试一次性扫描数据库查询的整个结果集。你不能这样做;你需要逐行读取,每次读取一行,将其转换为字节切片,然后再将字节切片转换为字符串。
由于你正在序列化为[]string
,每次保存字节切片并不是一个优先考虑的事情。在这种情况下,你可以使用sql.RawBytes
而不是[]byte
,它会重用相同的内存。
// 省略了错误检查
var row sql.RawBytes
myRow.Scan(&row) // 注意指针!
str := string(row)
英文:
It appears you're trying to scan the entire result set of that database query in one shot. You can't do that; you need to read each row, one at a time, into a byte slice, then convert the byte slice into a string.
Since you're serializing into a []string
, saving the byte slice each time is not a priority. In this case, you can use sql.RawBytes
instead of []byte
, which will reuse the same memory.
// error checking elided
var row sql.RawBytes
myRow.Scan(&row) // note the pointer!
str := string(row)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论