我想编写一个 Go 程序,使用 SELECT *
将数据库表中的行转储到 csv 文件中。
Go 提供了优秀的 sql和 csv api,但 csv
需要字符串数组,Rows
中的 Scan
方法会根据类型“填充”字段。
由于我之前不认识表格,所以我不知道有多少列以及它们的类型是什么。
这是我的第一个 Go 程序,所以我有点吃力。
如何最好地将 Rows
实例中的列读入 []string
- 这是“正确”的方式吗?
谢谢!
更新
我还在为这些参数而苦恼。这是我的代码,现在我使用 panic
而不是返回 error
,但我稍后会更改它。在我的测试中,我传递了查询结果和 os.Stdout
。
func dumpTable(rows *sql.Rows, out io.Writer) error {
colNames, err := rows.Columns()
if err != nil {
panic(err)
}
if rows.Next() {
writer := csv.NewWriter(out)
writer.Comma = '\t'
cols := make([]string, len(colNames))
processRow := func() {
err := rows.Scan(cols...)
if err != nil {
panic(err)
}
writer.Write(cols)
}
processRow()
for rows.Next() {
processRow()
}
writer.Flush()
}
return nil
}
为此,我得到 cannot use cols (type []string) as type []interface {} in function argument
(在 writer.Write(cols)
行。
然后我测试了
readCols := make([]interface{}, len(colNames))
writeCols := make([]string, len(colNames))
processRow := func() {
err := rows.Scan(readCols...)
if err != nil {
panic(err)
}
// ... CONVERSION?
writer.Write(writeCols)
}
这导致 panic :sql:列索引 0 上的扫描错误:目标不是指针
。
更新 2
我独立到达了ANisus ' 解决方案。这是我现在使用的代码。
func dumpTable(rows *sql.Rows, out io.Writer) error {
colNames, err := rows.Columns()
if err != nil {
panic(err)
}
writer := csv.NewWriter(out)
writer.Comma = '\t'
readCols := make([]interface{}, len(colNames))
writeCols := make([]string, len(colNames))
for i, _ := range writeCols {
readCols[i] = &writeCols[i]
}
for rows.Next() {
err := rows.Scan(readCols...)
if err != nil {
panic(err)
}
writer.Write(writeCols)
}
if err = rows.Err(); err != nil {
panic(err)
}
writer.Flush()
return nil
}
最佳答案
为了直接扫描
值到[]string
,你必须创建一个[]interface{}
slice 指向每个字符串 slice 中的字符串。
这里有一个 MySQL 的工作示例(只需更改 sql.Open
命令以匹配您的设置):
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"database/sql"
)
func main() {
db, err := sql.Open("mysql", "user:pass@tcp(localhost:3306)/test?charset=utf8")
defer db.Close()
if err != nil {
fmt.Println("Failed to connect", err)
return
}
rows, err := db.Query(`SELECT 'one' col1, 'two' col2, 3 col3, NULL col4`)
if err != nil {
fmt.Println("Failed to run query", err)
return
}
cols, err := rows.Columns()
if err != nil {
fmt.Println("Failed to get columns", err)
return
}
// Result is your slice string.
rawResult := make([][]byte, len(cols))
result := make([]string, len(cols))
dest := make([]interface{}, len(cols)) // A temporary interface{} slice
for i, _ := range rawResult {
dest[i] = &rawResult[i] // Put pointers to each string in the interface slice
}
for rows.Next() {
err = rows.Scan(dest...)
if err != nil {
fmt.Println("Failed to scan row", err)
return
}
for i, raw := range rawResult {
if raw == nil {
result[i] = "\\N"
} else {
result[i] = string(raw)
}
}
fmt.Printf("%#v\n", result)
}
}
关于sql - 将 "SELECT *"列读入 []string in go,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55611846/