英文:
Golang slices of struct or newbie trouble building REST
问题
我需要你的帮助。
我想构建一个简单的API,但遇到了一些问题。
我选择了gint和postgres驱动的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")
}
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)
但是如何做到这一点...不知道
英文:
and need your help.
Wanted to build simple api and stuck with some problem.
I've choose gin and database/sql with 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")
}
I need to make query to DB and make json out of this request.
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)
}
}
This coda working nice, but when i need to make json.
I need to make struct of a row
type Message struct {
ticket_id int `json:"ticket_id"`
event string `json:"event"`
}
an then i need to create slice , and append every rows.Next() loop an than answer to browser with Json...
c.JSON(200, messages)
But how to do that...don't know
答案1
得分: 1
免责声明:我对Go语言还不太熟悉。
由于你已经使用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"
}
英文:
disclaimer: I am brand new to go
Since you Scan
ned your column data into your variables, you should be able to initialize a structure with their values:
m := &Message{ticket_id: ticket_id, event: event}
You could initialize a slice with
s := make([]*Message, 0)
And then append each of your message structs after instantiation:
s = append(s, m)
Because I'm not too familiar with go there are a couple things i'm not sure about:
-
after copying data from query to your vars using
rows.Scan
does initializing theMessage
struct copy the current iterations values as expected?? -
If there is a way to get the total number of rows from your query it might be slighlty more performant to initialize a static length array, instead of a slice?
-
I think @inf deleted answer about marshalling your
Message
to json down the line might need to be addressed, andMessage
field's might need to be capitalized
copied from @inf:
> The names of the members of your struct need be capitalized so that
> they get exported and can be accessed.
>
> type Message struct {
> Ticket_id int json:"ticket_id"
> Event string json:"event"
}
答案2
得分: 0
我稍微作弊一下,顺便修复一些问题:
首先,在程序启动时只需打开一次数据库连接池(而不是在每个请求中都打开)。
其次,我们将使用 sqlx 来更轻松地将数据库行转换为结构体。
package main
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/jmoiron/sqlx"
)
var db *sqlx.DB
func main() {
var err error
// sqlx.Connect 也会检查连接是否正常工作。
// sql.Open 只是“建立”一个连接池,但不会 ping 数据库。
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")
// 我们创建一个结构体切片来将行转换为结构体
var messages []*Message
// 从这里开始,我们可以并发安全地使用数据库连接池
err := db.Select(&messages, "SELECT ticket_id, event FROM ... WHERE ... = $1", word)
if err != nil {
http.Error(c.Writer, err.Error(), 500)
return
}
// 使用 gin-gonic 的 JSON writer 输出结果
c.JSON(200, messages)
}
希望这样清楚了。sqlx
还会为您调用 rows.Close()
,否则连接会保持挂起状态。
英文:
I'm going to cheat a little here and fix a few things along the way:
First: open your database connection pool once at program start-up (and not on every request).
Second: we'll use sqlx to make it easier to marshal our database rows into our struct.
<!-- language: lang-go -->
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)
}
I hope that's clear. sqlx
also takes care of calling rows.Close()
for you, which will otherwise leave connections hanging.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论