Working with Different Structs with Common Members Using Generics
In Go, you may encounter scenarios where you want to create generic functions that operate on different structs that share common members. However, directly accessing such common fields across union type constraints is not yet supported in Go 1.18.
Challenge:
Consider two message structs, Message and MulticastMessage, each containing fields of the same type, such as Android. You want to define a generic function to add these fields to both structs. However, using a type parameter constrained to an interface containing both structs does not allow direct access to their common fields.
Solution:
Solution 1: Type Switch
If there are only a few structs involved, a type switch can be employed:
<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>
Solution 2: Wrapper with Method
For a large number of structs, consider wrapping each struct with a method that implements the common functionality:
<code class="go">type wrappedMessage interface { *MessageWrapper | *MultiCastMessageWrapper SetConfig(c foo.Config) } func highPriority[T wrappedMessage](message T) T { message.SetConfig(messaging.Android{"some-value"}) return message }</code>
Solution 3: Reflection
If you have many structs, reflection may be a better option, though it requires addressable structs and fields:
<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>
Notes and Alternatives:
The above is the detailed content of How to Work with Different Structs with Common Members in Go Using Generics?. For more information, please follow other related articles on the PHP Chinese website!