dongyongmin5711 2016-04-18 07:39 采纳率: 100%
浏览 214
已采纳

无法将<nil>转换为类型...?

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: enter image description here

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 ' '

  • 写回答

1条回答 默认 最新

  • doubinduo3364 2016-04-18 10:31
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 在不同的执行界面调用同一个页面
  • ¥20 基于51单片机的数字频率计
  • ¥50 M3T长焦相机如何标定以及正射影像拼接问题
  • ¥15 keepalived的虚拟VIP地址 ping -s 发包测试,只能通过1472字节以下的数据包(相关搜索:静态路由)
  • ¥20 关于#stm32#的问题:STM32串口发送问题,偶校验(even),发送5A 41 FB 20.烧录程序后发现串口助手读到的是5A 41 7B A0
  • ¥15 C++map释放不掉
  • ¥15 Mabatis查询数据
  • ¥15 想知道lingo目标函数中求和公式上标是变量情况如何求解
  • ¥15 关于E22-400T22S的LORA模块的通信问题
  • ¥15 求用二阶有源低通滤波将3khz方波转为正弦波的电路