无法转换< nil>成类型...? [英] Could't convert <nil> into type ...?

查看:299
本文介绍了无法转换< nil>成类型...?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 类型User 

使用数据库/ sql查询数据库行到Go类型,我的代码片段如下: struct {
user_id int64
user_name字符串
user_mobile字符串
密码字符串
电子邮件接口{}
昵称字符串
字节字节
锁定bool
create_time字符串
注释字符串// convert< nil> to * string error
}

func TestQueryUser(t * testing.T){
db:= QueryUser(driverName,dataSourceName)

stmtResults, err:= db.Prepare(queryAll)
defer stmtResults.Close()

var r * User = new(User)

arr:= [] interface {} {
& r.user_id,& r.user_name,& r.user_mobile,& r.password,& r.email,
& r.nickname,& r .level,& r.locked,& r.create_time,& r.comment,
}

err = stmtResults.QueryRow(username).Scan(arr ...)

if err!= nil {
t.Error(err.Error())
}

fmt.Println(r.email)


$ / code>

MySQL:



正如你所看到的,一些字段的值 NULL ,所以我必须设置接口{ } 键入Go的User struct,它将 NULL 转换为 nil

  --- FAIL:TestQueryUser(0.00s)
user_test.go:48:sql:列索引9上的扫描错误:不支持扫描,存储驱动程序。值类型< nil>到类型*字符串

有人有更好的方法吗?或者我必须更改MySQL字段并将其 DEFAULT''

解决方案

strong>在sql包中有一些类型,例如 sql.NullString (可为空字符串在你的表中,并猜测 Nullint64 NullBool 和... usage :)),你应该在你的结构中使用它们。

长:有两种可用的界面,第一种是扫描仪,另一个是

当您调用扫描功能时,会使用扫描仪。来自数据库驱动程序的数据通常位于 [] byte 中,并且您负责处理它。另一个是在查询中将该值用作输入时使用的。如果你只需要读取数据,Scanner就足够了,反之亦然,如果你需要在查询中写入参数,估值器就足够了,结果正常就是一片字节(和一个错误)。
$ b

作为实现示例,我建议您在 sql中查看类型包。



另外还有一个在postgresql中使用JSONB / JSON类型的例子

  // GenericJSONField用于处理postgres 
类型中的泛型json数据GenericJSONField map [string] interface {}


//扫描转换json字段进入我们的类型
func(v * GenericJSONField)Scan(src interface {})错误{
var b [] byte
switch src。(type){
case [] byte :
b = src。([] byte)
case string:
b = [] byte(src。(string))
case nil:
b = make([ ]字节,0)
默认值:
返回errors.New(不支持的类型)
}

返回json.Unmarshal(b,v)
}

//尝试获取数据库中的字符串切片表示形式
func(v GenericJSONField)Value()(driver.Value,error){
return json.Marshal (v)
}

驱动程序值通常 []字节但是 string ni l 是可以接受的。所以这也可以处理无效字段。

I tried to using database/sql for query database row into a Go type, my codes snippet following:

type User struct {
    user_id     int64
    user_name   string
    user_mobile string
    password    string
    email       interface{}
    nickname    string
    level       byte
    locked      bool
    create_time string
    comment     string  // convert <nil> to *string error 
}

func TestQueryUser(t *testing.T) {
    db := QueryUser(driverName, dataSourceName)

    stmtResults, err := db.Prepare(queryAll)
    defer stmtResults.Close()

    var r *User = new(User)

    arr := []interface{}{
        &r.user_id, &r.user_name, &r.user_mobile, &r.password, &r.email,
        &r.nickname, &r.level, &r.locked, &r.create_time, &r.comment,
    }

    err = stmtResults.QueryRow(username).Scan(arr...)

    if err != nil {
        t.Error(err.Error())
    }

    fmt.Println(r.email)

}

MySQL:

As your see, some fields that has NULL value, so I have to set interface{} type into User struct of Go, which convert NULL to nil.

--- FAIL: TestQueryUser (0.00s)
        user_test.go:48: sql: Scan error on column index 9: unsupported Scan, storing driver.Value type <nil> into type *string

Somebody has a better way? or I must change the MySQL field and set its DEFAULT ' '

解决方案

First the short answer : There is some types in sql package for example sql.NullString (for nullable string in your table and guess Nullint64 and NullBool and ... usage :) ) and you should use them in your struct.

The long one : There is two interface for this available in go , first is Scanner and the other is Valuer for any special type in database, (for example,I use this mostly with JSONB in postgres) you need to create a type, and implement this two(or one of them) interface on that type.

the scanner is used when you call Scan function. the data from the database driver, normally in []byte is the input and you are responsible for handling it. the other one, is used when the value is used as input in query. the result "normally" is a slice of byte (and an error) if you need to only read data, Scanner is enough, and vice-versa, if you need to write parameter in query the Valuer is enough

for an example of implementation, I recommend to see the types in sql package.

Also there is an example of a type to use with JSONB/JSON type in postgresql

// GenericJSONField is used to handle generic json data in postgres
type GenericJSONField map[string]interface{}


// Scan convert the json field into our type
func (v *GenericJSONField) Scan(src interface{}) error {
    var b []byte
    switch src.(type) {
    case []byte:
        b = src.([]byte)
    case string:
        b = []byte(src.(string))
    case nil:
        b = make([]byte, 0)
    default:
        return errors.New("unsupported type")
    }

    return json.Unmarshal(b, v)
}

// Value try to get the string slice representation in database
func (v GenericJSONField) Value() (driver.Value, error) {
    return json.Marshal(v)
}

driver value is often []byte but string and nil is acceptable. so this could handle null-able fields too.

这篇关于无法转换&lt; nil&gt;成类型...?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆