英文:
How to create a copy of a struct only having interface it implements and it's value
问题
假设我有一个实现了Setter
接口的A
结构体:
type Setter interface {
Set(key string, value string)
}
type A struct {
m map[string]string
}
func (a *A) Set(key string, value string) {
a.m[key] = value
}
我还有一个不同的结构体,它保存了Setter
接口的一些实现:
type Holder struct {
val Setter
}
h := Holder{
val: &A{ map[string]string{} },
}
我需要得到一个包含所有保存值的h.val
结构体的副本。
我已经尝试了以下解决方案,但它不起作用,导致panic: assignment to entry in nil map
错误:
(我们在初始化h
时定义了map,所以运行h.val.Set(k, v)
不会出错)
l := reflect.New(
reflect.ValueOf(h.val).Elem().Type(),
).Interface().(Setter)
l.Set("A", "B")
在不知道结构体包含哪些字段的情况下,我该如何创建一个结构体的副本,只知道它实现了哪个接口,并且将其值存储在一个变量中?
附注:向Setter
接口添加Clone
方法不是首选解决方案
英文:
Let's say I have this A
struct that implements Setter
interface:
type Setter interface {
Set(key string, value string)
}
type A struct {
m map[string]string
}
func (a *A) Set(key string, value string) {
a.m[key] = value
}
And I have one different struct that holds some implementation of Setter
interface
type Holder struct {
val Setter
}
h := Holder{
val: &A{ map[string]string{} },
}
What i need is to get a copy of the h.val
struct with all values saved.
I have already tried the following solution but it did not work, resulting with panic: assignment to entry in nil map
(We have defined the map when initiallizing h
, so by running h.val.Set(k, v)
we won't get any errors)
l := reflect.New(
reflect.ValueOf(h.val).Elem().Type(),
).Interface().(Setter)
l.Set("A", "B")
How can I create a copy of a struct without knowing which fields it consists of, only knowing the interface it implements and having it's value in a variable?
p.s. Adding Clone
method to Setter
interface is not a preferred solution
答案1
得分: 1
在所有情况下,将Clone
方法添加到Setter
接口并不是首选解决方案,因为只有Setter
的实现知道应该如何进行“克隆”,选择余地不多。
例如:克隆A
结构体应该创建一个指向相同映射的新结构体吗?还是应该复制映射?
如果你的意图真的是要克隆,你可能想要第二种情况,但你会发现这很快就超出了简单的reflect
操作的范围。
如果你的代码实际上只处理A
结构体,你可以传递显式的A
值。你可能仍然需要一个.Clone()
方法或一个Clone(a *A)
函数。
如果你的唯一问题是A
的零值是无效的,你可以修复Set()
:
func (a *A) Set(key string, value string) {
if a.m == nil {
a.m = make(map[string]string)
}
a.m[key] = value
}
英文:
> Adding Clone method to Setter interface is not a preferred solution
in all generality, since only the Setter
implementation knows how it should be "cloned", there isn't much choice.
For example : should "cloning" an A
struct create a new struct pointing at the same mapping ? or should it duplicate the mapping ?
If your intention is really to clone, you probably want the second, but you can see it will quickly fall outside the scope of a simple reflect
operation.
If your code actually only deals with A
structs, you may pass explicit A
values. You will probably still need a .Clone()
method or a Clone(a *A)
function.
If your only issue is that a zero value for A
is invalid, you can fix Set()
:
func (a *A) Set(key string, value string) {
if a.m == nil {
a.m = make(map[string]string)
}
a.m[key] = value
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论