英文:
Retrieving data from GORM Raw() Query
问题
我正在尝试通过项目学习来学习Golang。我给自己提出了一个问题,模拟顾客将产品添加到购物车中。目前,我有一个名为Cart.go
的模型,如下所示:
type Cart struct {
ID string
Customer Customer
CustomerID string
Product Product
ProductID string
CreatedAt time.Time
UpdatedAt time.Time
}
在Cart模型中,我定义了一个函数:
func (c *Cart) GetAllItemsInCart(db *gorm.DB, customer_id string) (*gorm.DB, error) {
items := db.Raw("SELECT id, product_id FROM carts WHERE customer_id = ?", customer_id).Scan(&c)
return items, nil
}
这个函数在一个控制器中被调用:
func (server *Server) GetAllCartItems(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
cart := models.Cart{}
items, err := cart.GetAllItemsInCart(server.DB, id)
if err != nil {
responses.ERROR(w, http.StatusInternalServerError, err)
return
}
responses.JSON(w, http.StatusOK, items)
}
据我了解,Scan()
函数将扫描结构体的值,或者在这种情况下将加载找到的数据到指定的结构体中。然而,我收到的响应是:
{
"Value": null,
"Error": null,
"RowsAffected": 2
}
这给了我50%的希望,因为"RowsAffected": 2是正确的。然而,显然返回的有效载荷响应不是我想要的。任何指导将不胜感激,谢谢。
英文:
I am trying to learn Golang via project based learning. The problem I have placed before myself to simulate customers adding products to their cart. Currently, I have the Cart.go
model as such..
type Cart struct {
ID string
Customer Customer
CustomerID string
Product Product
ProductID string
CreatedAt time.Time
UpdatedAt time.Time
}
On the Cart model, I have a function defined as
func (c *Cart) GetAllItemsInCart(db *gorm.DB, customer_id string) (*gorm.DB, error) {
items := db.Raw("SELECT id, product_id FROM carts WHERE customer_id = ?", customer_id).Scan(&c)
return items, nil
}
This function is called in a controller
func (server *Server) GetAllCartItems(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
cart := models.Cart{}
items, err := cart.GetAllItemsInCart(server.DB, id)
if err != nil {
responses.ERROR(w, http.StatusInternalServerError, err)
return
}
responses.JSON(w, http.StatusOK, items)
}
As I understand it currently is that Scan()
will scan the value of a struct, or in this case load the data found into the specified struct. However, the response I am seeing come back is
{
"Value": null,
"Error": null,
"RowsAffected": 2
}
Which gives me 50% hope because "RowsAffected": 2 would be correct. However, the payload response is obviously not what I am looking for. Any guidance would be greatly appreciated, thank you.
答案1
得分: 1
Scan
将值放入你提供的变量指针(通过via &c
),并返回一个数据库事务对象。你将该事务对象称为items
,但实际上它并不是items
。items
(即购物车的内容)在c *Cart
中,而不是在Scan
返回的对象中。
你的方法通过填充c
来修改它,不需要返回任何东西,除非你想返回Scan
可能返回的错误。
所以,你应该这样做:
err := cart.GetAllItemsInCart(server.DB, id)
// ...
responses.JSON(w, http.StatusOK, cart)
英文:
Scan
places the value into the pointer to a variable you've given it (via &c
), and returns a database transaction object. You're calling that transaction object items
, which it isn't. The items (ie, the contents of your cart) are in c *Cart
, not in the thing returned by Scan
.
Your method modifies c
by filling it, it doesn't have to return anything, unless you want to return the error that Scan
may return.
Instead of this...
items, err := cart.GetAllItemsInCart(server.DB, id)
// ...
responses.JSON(w, http.StatusOK, items)
You should be doing this:
err := cart.GetAllItemsInCart(server.DB, id)
// ...
responses.JSON(w, http.StatusOK, cart)
答案2
得分: 0
你需要修复几个问题:
- 你需要使用
Scan(c)
而不是Scan(&c)
,因为c
已经是一个指针。 - 你应该始终检查错误。在你的
GetAllItemsInCart
方法中,你没有传递或检查错误。从技术上讲,你确实传递了它(在items
对象内部),但你没有在任何地方检查它。 - 没有必要将
*gorm.DB
指针传递到更高层。
如果你想保留代码的结构,可以像这样修改:
func (c *Cart) GetAllItemsInCart(db *gorm.DB, customer_id string) error {
return db.Raw("SELECT id, product_id FROM carts WHERE customer_id = ?", customer_id).Scan(c).Error
}
// controller
func (server *Server) GetAllCartItems(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
cart := models.Cart{}
err := cart.GetAllItemsInCart(server.DB, id)
if err != nil {
responses.ERROR(w, http.StatusInternalServerError, err)
return
}
responses.JSON(w, http.StatusOK, cart)
}
英文:
You will need to fix a couple of things:
- You will need to use
Scan(c)
instead ofScan(&c)
sincec
is already a pointer. - You should always check for errors. In your
GetAllItemsInCart
method, you don't pass or check the error. Technically, you do pass it (inside theitems
object), but you do not check it anywhere. - There is no need to pass the
*gorm.DB
pointer higher up.
If you want to preserve the structure of the code the way you already started, it could look something like this:
func (c *Cart) GetAllItemsInCart(db *gorm.DB, customer_id string) error {
return db.Raw("SELECT id, product_id FROM carts WHERE customer_id = ?", customer_id).Scan(c).Error
}
// controller
func (server *Server) GetAllCartItems(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
cart := models.Cart{}
err := cart.GetAllItemsInCart(server.DB, id)
if err != nil {
responses.ERROR(w, http.StatusInternalServerError, err)
return
}
responses.JSON(w, http.StatusOK, cart)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论