Home > Software engineering >  invalid operation: cannot call non-function mysql.MysqlDB.Save(product).Error (variable of type erro
invalid operation: cannot call non-function mysql.MysqlDB.Save(product).Error (variable of type erro

Time:08-01

Thanks, man. I solved the problem.

There was a problem with Gorm calling Error(), so I wrote it like this and it worked fine:

package service

import (
   "iris-seckill/db/mysql"
   "iris-seckill/model"
)

type IProductService interface {
   GetProductByID(int64) (*model.Product, error)
   GetAllProduct() ([]*model.Product, error)
   DeleteProductByID(int64) error
   InsertProduct(product *model.Product) (int64, error)
   UpdateProduct(product *model.Product) error
}

type ProductService struct {
}

func NewProductService() IProductService {
   return &ProductService{}
}

func (p *ProductService) GetProductByID(productID int64) (*model.Product, error) {
   var product model.Product
   mysql.MysqlDB.Where("product_id = ?", productID).First(&product)
   return &product, nil
}

func (p *ProductService) GetAllProduct() (res []*model.Product, err error) {
   mysql.MysqlDB.Find(&res)
   return
}

func (p *ProductService) DeleteProductByID(productID int64) error {
   mysql.MysqlDB.Where("product_id = ?", productID).Delete(&model.Product{})
   return nil
}

func (p *ProductService) InsertProduct(product *model.Product) (int64, error) {
   mysql.MysqlDB.Create(product)
   return product.ProductID, nil
}

func (p *ProductService) UpdateProduct(product *model.Product) error {
   mysql.MysqlDB.Save(product)
   return nil
}

But it's not clear why.

I'm imitating the teacher in the online class,however, I encountered a very difficult error when using GORM.

Error: invalid operation: cannot call non-function mysql.MysqlDB.Save(product).Error (variable of type error)

The code of the controller layer is as follows:

package controller

import (
   "iris-seckill/model"
   "iris-seckill/service"

   "github.com/kataras/iris/v12"
   "github.com/kataras/iris/v12/mvc"
)

type ProductController struct {
   Ctx            iris.Context
   ProductService service.IProductService
}

func (p *ProductController) GetAll() (mvc.View, error) {
   products, err := p.ProductService.GetAllProduct()
   if err != nil {
      return mvc.View{}, err
   }
   return mvc.View{
      Name: "product/view.html",
      Data: iris.Map{
         "products": products,
      },
   }, nil
}

func (p *ProductController) PostUpdate() {
   product := &model.Product{}
   p.Ctx.Request().ParseForm()
   err := p.ProductService.UpdateProduct(product)
   if err != nil {
      p.Ctx.Application().Logger().Debug(err)
   }
   p.Ctx.Redirect("/product/all")
}

The code of the service layer is as follows:

package service

import (
   "iris-seckill/db/mysql"
   "iris-seckill/model"
)

type IProductService interface {
   GetProductByID(int64) (*model.Product, error)
   GetAllProduct() ([]*model.Product, error)
   DeleteProductByID(int64) error
   InsertProduct(product *model.Product) (int64, error)
   UpdateProduct(product *model.Product) error
}

type ProductService struct {
}

func NewProductService() IProductService {
   return &ProductService{}
}

func (p *ProductService) GetProductByID(productID int64) (*model.Product, error) {
   var product model.Product
   err := mysql.MysqlDB.Where("product_id = ?", productID).First(&product).Error()
   if err != nil {
      return nil, err
   }
   return &product, nil
}

func (p *ProductService) GetAllProduct() (res []*model.Product, err error) {
   err = mysql.MysqlDB.Find(&res).Error()
   return
}

func (p *ProductService) DeleteProductByID(productID int64) error {
   err := mysql.MysqlDB.Where("product_id = ?", productID).Delete(&model.Product{}).Error()
   return err
}

func (p *ProductService) InsertProduct(product *model.Product) (int64, error) {
   err := mysql.MysqlDB.Create(product).Error()
   if err != nil {
      return 0, err
   }
   return product.ProductID, nil
}

func (p *ProductService) UpdateProduct(product *model.Product) error {
   err := mysql.MysqlDB.Save(product).Error()
   return err
}

The main.go code is as follows:

package main

import (
   "context"
   "iris-seckill/backend/web/controller"
   "iris-seckill/conf"
   "iris-seckill/db/mysql"
   "iris-seckill/service"

   "github.com/kataras/iris/v12"
   "github.com/kataras/iris/v12/mvc"
   logging "github.com/sirupsen/logrus"
)

func main() {
   app := iris.New()
   app.Logger().SetLevel("debug")

   tmplate := iris.HTML("./backend/web/assets", ".html").Layout("share/layout").Reload(true)
   app.RegisterView(tmplate)

   app.HandleDir("/assets", "./backend/web/assets")

   app.OnAnyErrorCode(func(ctx iris.Context) {
      ctx.ViewData("message", ctx.Values().GetStringDefault("message", "访问的页面出错!"))
      ctx.ViewLayout("")
      ctx.View("share/error.html")
   })


   ctx, cancel := context.WithCancel(context.Background())
   defer cancel()
   productService := service.NewProductService()
   productParty := app.Party("/product")
   productApp := mvc.New(productParty)
   productApp.Register(ctx, productService)
   productApp.Handle(new(controller.ProductController))

   err := app.Run(
      iris.Addr(conf.IrisAddr),
      iris.WithoutServerError(iris.ErrServerClosed),
      iris.WithOptimizations,
   )
   if err != nil {
      logging.Info(err)
   }
}

func init() {
   conf.Init("./conf/config.ini")
   mysql.Init()
}

The project directory structure is as follows: https://i.imgur.com/FlYIOdD.png

The error message is as follows: https://i.imgur.com/Ycl5THQ.png

MysqlDB worked and passed the test.

I really don't know what's wrong, even debug is reporting an error.

I hope someone can help me, I appreciate any help you can give me.Thank you!

By the way, the only difference between me and the video teacher is that the teacher wrote his own database layer operations and I used Gorm,I wonder if that's the point.

CodePudding user response:

In Gorm, notice the difference between .Error and .Error()

To solve this problem,edit the code of the service layer is as follows:

package service

import (
   "iris-seckill/db/mysql"
   "iris-seckill/model"
)

type IProductService interface {
   GetProductByID(int64) (*model.Product, error)
   GetAllProduct() ([]*model.Product, error)
   DeleteProductByID(int64) error
   InsertProduct(product *model.Product) (uint, error)
   UpdateProduct(product *model.Product) error
}

type ProductService struct {
}

func NewProductService() IProductService {
   return &ProductService{}
}

func (p *ProductService) GetProductByID(id int64) (*model.Product, error) {
   var product model.Product
   err := mysql.MysqlDB.Where("id = ?", id).First(&product).Error
   return &product, err
}

func (p *ProductService) GetAllProduct() (res []*model.Product, err error) {
   err = mysql.MysqlDB.Find(&res).Error
   return
}

func (p *ProductService) DeleteProductByID(id int64) error {
   err := mysql.MysqlDB.Where("id = ?", id).Delete(&model.Product{}).Error
   return err
}

func (p *ProductService) InsertProduct(product *model.Product) (uint, error) {
   err := mysql.MysqlDB.Create(product).Error
   return product.ID, err
}

func (p *ProductService) UpdateProduct(product *model.Product) error {
   err := mysql.MysqlDB.Save(product).Error
   return err
}

It was really my carelessness.

  • Related