英文:
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)sincecis already a pointer. - You should always check for errors. In your
GetAllItemsInCartmethod, you don't pass or check the error. Technically, you do pass it (inside theitemsobject), but you do not check it anywhere. - There is no need to pass the
*gorm.DBpointer 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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论