我编写了一个Golang代码示例,它将查询发送到postgres并将结果发送到寻呼机:
package main
import (
"fmt"
"database/sql"
_ "github.com/lib/pq"
"log"
"os/exec"
"strings"
"os"
)
func main() {
connstr := "user=postgres dbname=postgres sslmode=disable"
db, err := sql.Open("postgres", connstr)
if err != nil { log.Fatal(err) }
rows, err := db.Query("SELECT schemaname, relname, seq_scan FROM pg_stat_all_tables ORDER BY 1 LIMIT 10")
if err != nil { log.Fatal(err) }
defer rows.Close()
var buf string
for rows.Next() {
var s, r string
var ss int
if err := rows.Scan(&s, &r, &ss); err != nil { log.Fatal(err) }
buf = fmt.Sprintf("%s %s %d\n", buf + s, r, ss)
}
cmd := exec.Command("less")
cmd.Stdin = strings.NewReader(buf)
cmd.Stdout = os.Stdout
err = cmd.Run()
if err != nil { log.Fatal(err) }
}
但是以下一行:
buf = fmt.Sprintf("%s %s %d\n", buf + s, r, ss)
对我来说看起来很粗鲁,我不确定这是不对的。有没有办法以更优雅的方式达到效果?可能有某种缓冲区和io.Readers吗?
答案 0 :(得分:0)
Go中的字符串是不可变的,每次为变量赋值时,它必须创建一个新字符串并将现有字符串的内容复制到其中。
您可以使用bytes.Buffer
代替string
来避免每次迭代重新播放。
package main
import (
"fmt"
"database/sql"
_ "github.com/lib/pq"
"log"
"os/exec"
"strings"
"os"
"bytes"
)
func main() {
connstr := "user=postgres dbname=postgres sslmode=disable"
db, err := sql.Open("postgres", connstr)
if err != nil { log.Fatal(err) }
rows, err := db.Query("SELECT schemaname, relname, seq_scan FROM pg_stat_all_tables ORDER BY 1 LIMIT 10")
if err != nil { log.Fatal(err) }
defer rows.Close()
var buf = new(bytes.Buffer)
for rows.Next() {
var s, r string
var ss int
if err := rows.Scan(&s, &r, &ss); err != nil { log.Fatal(err) }
buf.WriteString(fmt.Sprintf("%s %s %d\n", s, r, ss))
}
cmd := exec.Command("less")
cmd.Stdin = buf
cmd.Stdout = os.Stdout
err = cmd.Run()
if err != nil { log.Fatal(err) }
}
顺便说一句,字符串构建器已添加到Go 1.10 https://godoc.org/strings#Builder
中阅读有关字符串连接基准的更多信息:http://herman.asia/efficient-string-concatenation-in-go
答案 1 :(得分:0)
你现在所做的唯一问题是连接运算符+
是一种将很多字符串组合成一个更大的字符串的极其低效的方法。
效率如何?好here's a benchmark I did测试了三种方法:
BenchmarkMultiplyBasic 300000 4240 ns/op
BenchmarkMultiplyJoinBasic 200000 9942 ns/op
BenchmarkMultiplyConcatenationsBasic 10000 170523 ns/op
最后一个是连接运算符+
,与几个替代方案相比,显示出真正悲惨的性能。
在简化的可运行示例中,这是一种更有效的方法:
package main
import(
"fmt"
"strconv"
"strings"
)
type result struct {
s, r string
ss int
}
func main() {
a := []result{
{"twas", "brillig", 1},
{"and", "the", 2},
{"slithy", "toves", 3},
}
outstrings := make([]string, 0)
for _, part := range a {
outstrings = append(outstrings, part.s, part.r, strconv.Itoa(part.ss))
}
out := strings.Join(outstrings, ` `)
fmt.Printf("%s\n", out)
}
打印
twas brillig 1 and the 2 slithy toves 3
如何最有效地组合字符串是StackOverflow上的常见问题,并且已经多次回答。请参阅此最高投票的问题/答案:How to efficiently concatenate strings in Go?。