Setting variable type at run-time in Go

huangapple go评论90阅读模式
英文:

Setting variable type at run-time in Go

问题

我有以下的Go函数,它使用了Gorm的First()方法:

func (r *SqlRepository) Get(id int, inventory any) (any, error) {
    result := db.First(&inventory, id)

    if result.Error != nil {
        var s struct{}
        return s, result.Error
    } else {
        return inventory, nil
    }
}

当调用Get函数并传入一个整数和我创建的一个结构体(Get(1, model.InventoryToys{}))时,我得到以下错误:

panic: reflect: reflect.Value.Set using unaddressable value

根据我的理解,any表示该值可以是任何类型,所以当我传入model.InventoryToys{}时,它应该成为inventory的类型。在Go中是不是不是这样工作的?我有什么遗漏吗?

为了提供背景,我之所以希望它是any类型,是因为我有多个用于库存的表格和多个结构体作为结果,我不想为每个结构体创建一个单独的获取函数,以避免代码重复。因此,我试图动态地将inventory的类型分配为传入的任何类型,并让Gorm去获取指定表格的数据。

英文:

I have the following Go function which uses Gorm's First():

func (r *SqlRepository) Get(id int, inventory any) (any, error) {
	result := db.First(&inventory, id)

	if result.Error != nil {
		var s struct{}
		return s, result.Error
	} else {
		return inventory, nil
	}
}

When calling that Get and passing an int and a struct created by me (Get(1, model.InventoryToys{})) I am getting

panic: reflect: reflect.Value.Set using unaddressable value

From my understanding any means that that value can be anything so when I pass model.InventoryToys{} that should become the type of inventory. Is that not how it works in Go? Am I missing something?

Just for context the reason I want it to be any is because I have multiple tables for inventory and multiple structs as a result and I didn't want to create a separate get function for each one of them to avoid code repetition. So essentially I am trying to dynamically assign the type of inventory to whatever is passed and let Gorm go and get data from the specified table.

答案1

得分: 2

any是一个没有指定方法的接口,因此所有的数据类型都可以用any来表示。

Go是一种静态类型语言,所以你不能在运行时设置变量的类型。inventory的类型是anyinventory可以包含不同类型的不同值。在你的情况下,inventory包含了一个类型为model.InventoryToys的值。这不是一个可写的类型,它的地址不能被获取,因为它是一个值的副本。

如果你使用*model.InventoryToys,那么它就变成了可写的,因为inventory现在包含了一个指向结构体的指针,可以对它进行写操作。

所以,你必须将inventory设置为&model.InventoryToys,并将inventory传递给db.First,而不是&inventory

英文:

any is an interface that specified no methods, so all data types can be represented by any.

Go is a statically typed language, so you cannot set the type of a variable at runtime. The type of inventory is any. inventory can contain different values of different types. In your case, inventory contains a value of type model.InventoryToys. This is not a writable type, its address cannot be taken, because it is the copy of a value.

If you use *model.InventoryToys, then it becomes writable, because inventory now contains a pointer to a struct, and it can be written.

So, you have to set inventory to &model.InventoryToys, and pass inventory into db.First, and not &inventory.

答案2

得分: 0

你可以按照下面的方式修改Get函数。

func (r *SqlRepository) Get(id int, inventory interface{}) (interface{}, error) {
    result := db.First(inventory, id)
    if result.Error != nil {
        var s struct{}
        return s, result.Error
    } else {
        return inventory, nil
    }
}

你需要将可设置的值解析为db.First函数的指针。它应该是一个模型的指针,而不是一个接口的指针。在gorm中,他们使用了反射。请参考反射定律获取更多信息。

你可以按照下面的方式调用Get函数。

repo := SqlRepository{}
id := 1
toys := &model.InventoryToys{}
repo.Get(id, &toys)
英文:

You can modify the Get function as shown below.

func (r *SqlRepository) Get(id int, inventory any) (any, error) {
 result := db.First(inventory, id)
 if result.Error != nil {
  var s struct{}
  return s, result.Error
 } else {
  return inventory, nil
 }
}

You need to parse settable value to the db.First function. It should be a pointer of a model & shouldn't be a pointer of an interface. In side gorm, they use reflection. Refer Laws of reflection for more information.

You can call Get function as shown below.

 repo := SqlRepository{}
 id := 1
 toys := &model.InventoryToys{}
 repo.Get(id, &toys)

huangapple
  • 本文由 发表于 2023年3月19日 12:10:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75780034.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定