亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

當我在 db(此處為 postgres)中的結構未知時,如何檢索 GoLang 數據庫/sql

當我在 db(此處為 postgres)中的結構未知時,如何檢索 GoLang 數據庫/sql

Go
繁星coding 2022-06-01 17:52:23
我使用 github.com/lib/pq 將 Go 與 PostgreSQL 一起使用,并且在我的結構已知時能夠成功獲取記錄?,F在我的查詢是當我的結構動態變化時如何獲取記錄?通過rows.columns我可以獲取列名,但是您能幫我獲取所有行的這些列的值嗎?我引用了@Luke 回答的這個鏈接,不過,這里的人已經定義了一個結構。 是否可以使用 GoLang 數據庫/sql 按名稱檢索列值type Person struct {    Id int    Name string}同時,我沒有固定的結構,所以我將如何遍歷所有列,對所有行再次進行迭代。我的方法是先用一個指針循環遍歷所有列,然后再循環遍歷下一行。仍然無法對此進行編碼,請您幫我解決這個問題,例如如何繼續并獲取值。
查看完整描述

3 回答

?
慕尼黑8549860

TA貢獻1818條經驗 獲得超11個贊

由于您事先不知道結構,您可以將行作為空接口的二維切片返回。但是,要使行掃描起作用,您需要將值預分配給適當的類型,為此您可以使用ColumnTypes方法和reflect包。請記住,并非每個驅動程序都提供對列類型的訪問,因此請確保您使用的驅動程序提供。


rows, err := db.Query("select * from foobar")

if err != nil {

    return err

}

defer rows.Close()


// get column type info

columnTypes, err := rows.ColumnTypes()

if err != nil {

    return err

}


// used for allocation & dereferencing

rowValues := 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 info

columnTypes, err := rows.ColumnTypes()

if err != nil {

    return err

}


// used for allocation & dereferencing

rowValues := 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)


查看完整回答
反對 回復 2022-06-01
?
慕斯709654

TA貢獻1840條經驗 獲得超5個贊

此函數在不知道列類型和計數的情況下打印查詢結果。這是不使用包的先前答案的變體。reflect


func 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 ...。


查看完整回答
反對 回復 2022-06-01
?
小怪獸愛吃肉

TA貢獻1852條經驗 獲得超1個贊

此函數在不知道列類型和計數的情況下打印查詢結果。這是不使用包的先前答案的變體。reflect


func 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 ...。


查看完整回答
反對 回復 2022-06-01
  • 3 回答
  • 0 關注
  • 120 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號