编写通用函数来操作共享公共成员的多个结构体可能具有挑战性,特别是当这些结构属于外部包时。本文探讨了解决此场景的各种解决方案。
考虑编写一个向 Firebase 消息结构(包括 Message 和 MulticastMessage)添加特定字段的函数。这两个结构体都包含相同类型的 Android 和 APNS 字段,但它们没有显式声明彼此之间的关系。
最初,人们可能会尝试定义一个通用接口 firebaseMessage ,并按如下方式实现该函数:
<code class="go">type firebaseMessage interface { *messaging.Message | *messaging.MulticastMessage } func highPriority[T firebaseMessage](message T) T { message.Android = &messaging.AndroidConfig{...} .... return message }</code>
但是,由于错误“message.Android undefined (type T has no field or method Android)”,此方法失败。
一个简单的解决方案涉及使用类型开关来单独处理每个特定的结构类型:
<code class="go">func highPriority[T firebaseMessage](message T) T { switch m := any(message).(type) { case *messaging.Message: setConfig(m.Android) case *messaging.MulticastMessage: setConfig(m.Android) } return message }</code>
如果联合中的类型数量有限,这将有效。
如果必须访问公共成员,一种方法是使用可由联合体中的所有结构调用的公共方法创建一个包装结构。缺点是必须为不同类型创建多个包装结构体:
<code class="go">type wrappedMessage interface { *MessageWrapper | *MultiCastMessageWrapper SetConfig(c foo.Config) } type MessageWrapper struct { messaging.Message } func (w *MessageWrapper) SetConfig(cfg messaging.Android) { *w.Android = cfg } // same for MulticastMessageWrapper</code>
对于结构体较多的情况,反射可能是更合适的解决方案。
<code class="go">func highPriority[T firebaseMessage](message T) T { cfg := &messaging.Android{} reflect.ValueOf(message).Elem().FieldByName("Android").Set(reflect.ValueOf(cfg)) return message }</code>
请注意,由于此方法使用反射,因此必须确保字段可寻址。
根据具体要求,适当的解决方案可能会有很大差异。本文提供了几种在 Go 中处理此类场景的可行选项。
以上是如何编写通用函数来处理 Go 中外部包中具有公共成员的结构?的详细内容。更多信息请关注PHP中文网其他相关文章!