-
慕尼黑8549860
由于您事先不知道结构,您可以将行作为空接口的二维切片返回。但是,要使行扫描起作用,您需要将值预分配给适当的类型,为此您可以使用ColumnTypes方法和reflect包。请记住,并非每个驱动程序都提供对列类型的访问,因此请确保您使用的驱动程序提供。rows, err := db.Query("select * from foobar")if err != nil { return err}defer rows.Close()// get column type infocolumnTypes, err := rows.ColumnTypes()if err != nil { return err}// used for allocation & dereferencingrowValues := make([]reflect.Value, len(columnTypes))for i := 0; i < len(columnTypes); i++ { // allocate reflect.Value representing a **T value rowValues[i] = reflect.New(reflect.PtrTo(columnTypes[i].ScanType()))}resultList := [][]interface{}{}for rows.Next() { // initially will hold pointers for Scan, after scanning the // pointers will be dereferenced so that the slice holds actual values rowResult := make([]interface{}, len(columnTypes)) for i := 0; i < len(columnTypes); i++ { // get the **T value from the reflect.Value rowResult[i] = rowValues[i].Interface() } // scan each column value into the corresponding **T value if err := rows.Scan(rowResult...); err != nil { return err } // dereference pointers for i := 0; i < len(rowValues); i++ { // first pointer deref to get reflect.Value representing a *T value, // if rv.IsNil it means column value was NULL if rv := rowValues[i].Elem(); rv.IsNil() { rowResult[i] = nil } else { // second deref to get reflect.Value representing the T value // and call Interface to get T value from the reflect.Value rowResult[i] = rv.Elem().Interface() } } resultList = append(resultList, rowResult)}if err := rows.Err(); err != nil { return err}fmt.Println(resultList)分享编辑跟随由于您事先不知道结构,您可以将行作为空接口的二维切片返回。但是,要使行扫描起作用,您需要将值预分配给适当的类型,为此您可以使用ColumnTypes方法和reflect包。请记住,并非每个驱动程序都提供对列类型的访问,因此请确保您使用的驱动程序提供。rows, err := db.Query("select * from foobar")if err != nil { return err}defer rows.Close()// get column type infocolumnTypes, err := rows.ColumnTypes()if err != nil { return err}// used for allocation & dereferencingrowValues := make([]reflect.Value, len(columnTypes))for i := 0; i < len(columnTypes); i++ { // allocate reflect.Value representing a **T value rowValues[i] = reflect.New(reflect.PtrTo(columnTypes[i].ScanType()))}resultList := [][]interface{}{}for rows.Next() { // initially will hold pointers for Scan, after scanning the // pointers will be dereferenced so that the slice holds actual values rowResult := make([]interface{}, len(columnTypes)) for i := 0; i < len(columnTypes); i++ { // get the **T value from the reflect.Value rowResult[i] = rowValues[i].Interface() } // scan each column value into the corresponding **T value if err := rows.Scan(rowResult...); err != nil { return err } // dereference pointers for i := 0; i < len(rowValues); i++ { // first pointer deref to get reflect.Value representing a *T value, // if rv.IsNil it means column value was NULL if rv := rowValues[i].Elem(); rv.IsNil() { rowResult[i] = nil } else { // second deref to get reflect.Value representing the T value // and call Interface to get T value from the reflect.Value rowResult[i] = rv.Elem().Interface() } } resultList = append(resultList, rowResult)}if err := rows.Err(); err != nil { return err}fmt.Println(resultList)
-
慕斯709654
此函数在不知道列类型和计数的情况下打印查询结果。这是不使用包的先前答案的变体。reflectfunc printQueryResult(db *sql.DB, query string) error { rows, err := db.Query(query) if err != nil { return fmt.Errorf("canot run query %s: %w", query, err) } defer rows.Close() cols, _ := rows.Columns() row := make([]interface{}, len(cols)) rowPtr := make([]interface{}, len(cols)) for i := range row { rowPtr[i] = &row[i] } fmt.Println(cols) for rows.Next() { err = rows.Scan(rowPtr...) if err != nil { fmt.Println("cannot scan row:", err) } fmt.Println(row...) } return rows.Err()}诀窍是rows.Scan可以将值扫描到*interface{},但您必须将其包装起来interface{}才能将其传递给Scanusing ...。
-
小怪兽爱吃肉
此函数在不知道列类型和计数的情况下打印查询结果。这是不使用包的先前答案的变体。reflectfunc printQueryResult(db *sql.DB, query string) error { rows, err := db.Query(query) if err != nil { return fmt.Errorf("canot run query %s: %w", query, err) } defer rows.Close() cols, _ := rows.Columns() row := make([]interface{}, len(cols)) rowPtr := make([]interface{}, len(cols)) for i := range row { rowPtr[i] = &row[i] } fmt.Println(cols) for rows.Next() { err = rows.Scan(rowPtr...) if err != nil { fmt.Println("cannot scan row:", err) } fmt.Println(row...) } return rows.Err()}诀窍是rows.Scan可以将值扫描到*interface{},但您必须将其包装起来interface{}才能将其传递给Scanusing ...。