0

并需要你的帮助。想要构建简单的 api 并遇到一些问题。我选择了带有postgres 驱动程序的gin和 database/sql

package main

import (
    "database/sql"
    "fmt"

    "github.com/gin-gonic/gin"

    _ "github.com/lib/pq"
)

func main() {

    router := gin.Default()
    router.GET("/search/:text", SearchWord)
    router.Run(":8080")

}

我需要查询 DB 并从这个请求中生成 json。

func checkErr(err error) {
    if err != nil {
        panic(err)
    }
}

type Message struct {
    ticket_id int    `json:"ticket_id"`
    event     string `json:"event"`
}

func SearchWord(c *gin.Context) {
    word := c.Params.ByName("text")
    db, err := sql.Open("postgres", "host=8.8.8.8 user= password= dbname=sample")
    defer db.Close()
    checkErr(err)
    rows, err2 := db.Query("SELECT ticket_id,event FROM ....$1, word)
    checkErr(err)
    for rows.Next() {
        var ticket_id int
        var event string
        err = rows.Scan(&ticket_id, &event)
        checkErr(err)
        fmt.Printf("%d | %s \n\n", ticket_id, event)
    }

}

这个尾声很好用,但是当我需要制作 json 时。我需要制作一行结构

type Message struct {
    ticket_id int    `json:"ticket_id"`
    event     string `json:"event"`
}

然后我需要创建切片,并附加每一行。Next() 循环一个比用 Json 回答浏览器...

c.JSON(200, messages)

但是如何做到这一点......不知道:(

4

2 回答 2

1

免责声明:我是全新的

由于您Scan将列数据嵌入到变量中,因此您应该能够使用它们的值初始化结构:

m := &Message{ticket_id: ticket_id, event: event}

你可以初始化一个切片

s := make([]*Message, 0)

然后在实例化后附加每个消息结构:

s = append(s, m)


因为我对 go 不太熟悉,所以有几件事我不确定:

  • rows.Scan使用初始化结构将数据从查询复制到您的变量后,是否会Message按预期复制当前迭代值?

  • 如果有一种方法可以从查询中获取总行数,那么初始化静态长度数组而不是切片可能会更高效?

  • 我认为@inf删除了关于将你Message的json编组到下线的答案可能需要解决,并且Message字段可能需要大写

从@inf 复制:

结构成员的名称需要大写,以便它们被导出并可以访问。

type Message struct {
    Ticket_id int    `json:"ticket_id"`
    Event     string `json:"event"` }
于 2015-07-05T18:15:06.050 回答
0

我将在这里作弊,并在此过程中解决一些问题:

首先:在程序启动时(而不是每次请求)打开一次数据库连接池。

第二:我们将使用sqlx来更轻松地将数据库行编组到我们的结构中。

package main

var db *sqlx.DB

func main() {
    var err error
    // sqlx.Connect also checks that the connection works.
    // sql.Open only "establishes" a pool, but doesn't ping the DB.
    db, err = sqlx.Connect("postgres", "postgres:///...")
    if err != nil {
        log.Fatal(err)
    }

    router := gin.Default()
    router.GET("/search/:text", SearchWord)
    router.Run(":8080")

}

// in_another_file.go

type Message struct {
    TicketID int    `json:"ticket_id" db:"ticket_id"`
    Event     string `json:"event" db:"event"`
}

func SearchWord(c *gin.Context) {
    word := c.Params.ByName("text")
    // We create a slice of structs to marshal our rows into
    var messages []*Message{}
    // Our DB connection pool is safe to use concurrently from here
    err := db.Select(&messages, "SELECT ticket_id,event FROM ....$1, word)
    if err != nil {
        http.Error(c.Writer, err.Error(), 500)
        return
    }

    // Write it out using gin-gonic's JSON writer.
    c.JSON(200, messages)
}

我希望这很清楚。sqlx还负责呼叫rows.Close()您,否则会导致连接挂起。

于 2015-07-05T21:21:04.750 回答