【问题标题】:Golang slices of struct or newbie trouble building RESTGolang 结构切片或新手在构建 REST 时遇到麻烦
【发布时间】:2017-03-14 10:44:39
【问题描述】:

需要你的帮助。 想要构建简单的 api 并遇到一些问题。 我选择了ginpostgres driver 的数据库/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")

}

我需要对数据库进行查询并从这个请求中生成 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)

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

【问题讨论】:

    标签: json postgresql rest go go-gin


    【解决方案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"` }
    

    【讨论】:

    • 如果你知道你想要的行数,make([]Message, 15) 的性能会更好,其中 15 是行数。
    【解决方案2】:

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

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

    第二:我们将使用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(),否则会导致连接挂起。

    【讨论】:

    • messages := []*Message 产生“语法错误:意外的分号或换行符,期待 {”我用“var messages []*Message”做到了但现在当 db.Select 错误处理时出错“具有 >1 列 (2) 的非结构 dest 类型结构”
    • 您选择了多少项目?如果它只是一个,你只需要一个Message - 如果它更多,你需要一个[]*Message
    • 选择错误是因为我需要像@inf 所说的那样制作大写变量。谢谢很多 4 个答案
    猜你喜欢
    • 1970-01-01
    • 2023-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 2016-12-24
    • 1970-01-01
    相关资源
    最近更新 更多