我想编写一个Go程序,以使用将从数据库表中的行转储到csv文件中SELECT *
。
Go提供了出色的sql和csv
api,但是csv
希望根据其类型Scan
在Rows
“填充”字段中使用字符串数组和方法。因为我之前不知道表,所以我不知道有多少列以及它们的类型。
这是我在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: Scan error on column index 0: destination not a pointer
。
更新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
}
为了Scan
将值直接转换为[]string
,您必须创建一个[]interface{}
指向字符串切片中每个字符串的切片。
在这里,您有一个适用的MySQL示例(只需更改sql.Open
-command以匹配您的设置):
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)
}
}
问题内容: 目前,我正在研究可用于读取url指定的网站内容的类。我刚开始我的冒险经历和,所以我需要咨询我的设计。 用法: 我的代码: 我的问题是:这是实现我想要的一个好方法吗?有更好的解决方案吗? 我特别不喜欢,但我无法用其他方式表达它。每次迭代都创建一个新的String很好吗?我想没有 还有其他弱点吗? 提前致谢! 问题答案: 考虑改为使用。此外,你可能想利用从Apache的百科全书IO使串阅读
问题内容: 我有一个如下的文本文件。我想读取给定值作为浮动列表。之后,我将进行一些计算。我使用了拆分功能和转换来浮动。但是我不能转换第一个和最后一个,因为这两个都有方括号。([])。它给出了如下错误。 文件格式 错误 我使用的代码 任何人都可以给我一个想法,如何将这些值读入如下所示的float数组中。 然后我可以调用X [1],X [999]之类的值 问题答案: 用于将每一行解析为浮点数列表: 每
问题内容: 这一定很明显,但我无法弄清楚。我为此花了将近一整天。我很乐意给减轻我体重的人买啤酒。 这是我的代码。我看到字节数组大小不合适,但是我找不到正确的大小。除此之外,内容也不是不正确的。似乎只有文字字符可以。 似乎从二进制文件中删除数据确实很痛苦,我真的很沮丧。 还有一件事:文件内容不是文本,可以是图片,视频或pdf之类的东西。 问题答案: 如果你正在读一个二进制文件,你应该 不 尝试把它当
我需要在一个映射中插入一些数据,该映射需要一个字符串作为键,一个字符串列表作为值,但我不知道怎么做。 这是我试图做的。 首先,我创建了一个HashMap,然后创建了一个新对象,现在出现了问题。 我创建了一个新的字符串列表,给它起了一个名字,然后我认为我必须使用“put”方法,但这是错误的,因为我有一个错误,告诉你:“方法put(String,List)在类型HashMap中 为什么是布尔值?当我在
问题内容: 我已将文件读入字符串。该文件包含各种名称,每行一个名称。现在的问题是,我希望将这些名称放在String数组中。 为此,我编写了以下代码: 但是我没有得到预期的结果,分割字符串后获得的数组长度为1。这意味着“ fileString”不具有“ \ n”字符,但是文件具有此“ \ n”字符。 那么如何解决这个问题呢? 问题答案: 问题不在于如何分割字符串。那一点是正确的。 您必须查看如何将文
getline() 是 istream 类的成员函数,它有如下两个重载版本: istream & getline(char* buf, int bufSize); istream & getline(char* buf, int bufSize, char delim); 第一个版本从输入流中读取 bufSize-1 个字符到缓冲区 buf,或遇到 为止(哪个条件先满足就按哪个执行)。函数会自动在