填充作为参数给出的接口类型的一部分(例如,为数据库/sql 实现 ScanAll)

我们如何实现一个函数,该函数将返回 SQL 查询产生的所有行并将它们转换为dest接口数组(可能无法正常工作Scan)?


我假设目标数组必须作为函数的参数给出。但是,我仍然不知道我应该如何完成实施:


func GetAll(query string, dest interface{}) error {


  rows, err := s.db.Query(query)

  if err != nil {

    return err

  }

  defer rows.Close()


  for rows.Next() {

    var destRow ??? /* do not have a type. using reflect.TypeOf(dest).Elem()? */

    err := rows.Scan(&destRow)

    if err != nil {

      return err

    }

    dest = append(dest, destRow) /* would even compile? */

  }

  return nil

}

它看起来与json.Unmarshal实际必须做的没什么不同......


青春有我
浏览 64回答 1
1回答

蛊毒传说

这是使用reflect 包的解决方案。使用指向切片的指针调用函数。func GetAll(query string, dest interface{}) error {    // Return error if dest is not a pointer to a slice.    slice := reflect.ValueOf(dest)    if slice.Kind() != reflect.Ptr {        return errors.New("dest must be pointer")    }    slice = slice.Elem()    if slice.Kind() != reflect.Slice {        return errors.New("dest must be pointer to struct")    }    rows, err := db.Query(query)    if err != nil {        return err    }    defer rows.Close()    for rows.Next() {        // Create a new slice element. The variable elementp holds a         // pointer to the new element.        elementp := reflect.New(slice.Type().Elem())        err := rows.Scan(elementp.Interface())        if err != nil {            return err        }        // Append the element to the slice.        slice.Set(reflect.Append(slice, elementp.Elem()))    }    return nil}当查询结果只有一列并且 dest 是指向适合该列的类型的切片时,上面的代码适用于标准的 database/sql 包。这是一个例子:var names []stringif err := GetAll(db, "select name from people", &names); err != nil {    // handle error}此代码还应与支持将多列扫描到结构的数据库包一起使用。
打开App,查看更多内容
随时随地看视频慕课网APP