Golang切片的结构或新手麻烦构建REST

时间:2015-07-05 16:10:15

标签: json postgresql rest go go-gin

需要你的帮助。 想要构建简单的api并遇到一些问题。 我选择gin和数据库/ sql与postgres driver

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"`
}

然后我需要创建切片,并附加每个rows.Next()循环而不是使用Json回答浏览器......

c.JSON(200, messages)

但是怎么做......不知道:(

2 个答案:

答案 0 :(得分:1)

免责声明:我是全新的

由于您m := &Message{ticket_id: ticket_id, event: event}将列数据添加到变量中,因此您应该能够使用其值初始化结构:

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

您可以使用

初始化切片

s = append(s, m)

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

rows.Scan

因为我不太熟悉去,有几件我不确定的事情:

  • 使用Message将数据从查询复制到您的变量后,初始化Message struct会按预期复制当前迭代值吗?

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

  • 我认为@inf已删除的答案有关将您的Message编组到json下线可能需要解决,type Message struct { Ticket_id int `json:"ticket_id"` Event string `json:"event"` } 字段可能需要大写

从@inf:

复制
  

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

data:{username: user, password: pass}

答案 1 :(得分: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(),否则将会挂起连接。