我正在使用denisenkom中的示例运行SQL
查询,但与http.ResponseWriter
结合使用,并且我在interface{}
类型转换方面苦苦挣扎。有几篇帖子与我正在做的事情很接近,但是解决方案似乎有点笨拙,总是使用fmt
(我没有使用)。
请注意,我的查询有效并返回结果。我只是想显示该结果。
这是我认为比较接近但无法正常工作的代码。我尝试了其他几件事,但什至没有编译。
vals := make([]interface{}, len(cols))
for i := 0; i < len(cols); i++ {
vals[i] = new(interface{})
if i != 0 {
w.Write([]byte("\t"))
}
w.Write([]byte(cols[i]))
}
for rows.Next() {
err = rows.Scan(vals...)
if err != nil {
w.Write([]byte("Row problem: " + err.Error()))
continue
}
for i := 0; i < len(vals); i++ {
if i != 0 {
w.Write([]byte("\t"))
}
//THIS IS THE PART I'M STUCK ON
switch v := vals[i].(type) {
case int:
w.Write([]byte("int!\n" + string(v)))
case int8:
w.Write([]byte("int8!\n" + string(v)))
//etc, etc
//more types
//etc, etc
case float64:
w.Write([]byte("float64!\n" + string(v))) //This fails, can't convert, will need something else
case string:
w.Write([]byte("string!\n" + v))
default:
w.Write([]byte("something else!\n"))
}
}
}
但是,是否存在更好的方法来动态检查基础类型并将其转换为可读性呢?我要做的只是吐出查询结果,这好像是我做错了什么。
请注意,即使它的类型明确相同,它也总是会碰到
default
的情况。 最佳答案
denisekom上的示例使用fmt.Print系列函数将其打印到stdout。使用fmt.Fprint系列函数将示例更改为打印到响应编写器。
fmt.Fprint函数写入指定为第一个参数的io.Writer。响应编写器满足io.Writer接口。这是原始示例中的修改后的代码,其中w
是http.ResponseWriter。
vals := make([]interface{}, len(cols))
for i := 0; i < len(cols); i++ {
vals[i] = new(interface{})
if i != 0 {
fmt.Fprint(w, "\t")
}
fmt.Fprint(w, cols[i])
}
fmt.Fprintln(w)
for rows.Next() {
err = rows.Scan(vals...)
if err != nil {
fmt.Fprintln(w, err)
continue
}
for i := 0; i < len(vals); i++ {
if i != 0 {
fmt.Fprint(w, "\t")
}
printValue(w, vals[i].(*interface{}))
}
fmt.Fprintln(w)
}
...
func printValue(w io.Writer, pval *interface{}) {
switch v := (*pval).(type) {
case nil:
fmt.Fprint(w, "NULL")
case bool:
if v {
fmt.Fprint(w, "1")
} else {
fmt.Fprint(w, "0")
}
case []byte:
fmt.Fprint(w, string(v))
case time.Time:
fmt.Fprint(w, v.Format("2006-01-02 15:04:05.999"))
default:
fmt.Fprint(w, v)
}
}
关于问题中的代码:
string(v)
表达式是字符串转换。字符串转换不会像代码所假定的那样将数字转换为十进制表示形式。有关字符串转换的详细信息,请参见spec。使用上面的fmt
包或strconv
包将数字转换为十进制字符串。类型开关应为switch v := (*(vals[i].(*interface{})).(type) {
。有点混乱,这引出了我的下一个观点。原始示例使用了比所需更多的间接寻址。这是简化的版本,随时可以与响应编写器一起调用:
func exec(w io.Writer, db *sql.DB, cmd string) error {
rows, err := db.Query(cmd)
if err != nil {
return err
}
defer rows.Close()
cols, err := rows.Columns()
if err != nil {
return err
}
if cols == nil {
return nil
}
vals := make([]interface{}, len(cols))
args := make([]interface{}, len(cols))
for i := 0; i < len(cols); i++ {
args[i] = &vals[i]
if i != 0 {
fmt.Fprint(w, "\t")
}
fmt.Fprint(w, cols[i])
}
for rows.Next() {
err = rows.Scan(args...)
if err != nil {
fmt.Fprintln(w, err)
continue
}
for i := 0; i < len(vals); i++ {
if i != 0 {
fmt.Print("\t")
}
printValue(w, vals[i])
}
fmt.Fprintln(w)
}
if rows.Err() != nil {
return rows.Err()
}
return nil
}
func printValue(w io.Writer, v interface{}) {
switch v := v.(type) {
case nil:
fmt.Fprint(w, "NULL")
case bool:
if v {
fmt.Fprint(w, "1")
} else {
fmt.Fprint(w, "0")
}
case []byte:
fmt.Fprint(w, string(v))
case time.Time:
fmt.Fprint(w, v.Format("2006-01-02 15:04:05.999"))
default:
fmt.Fprint(w, v)
}
}
关于go - http.ResponseWriter.Write with interface {},我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47662614/