Home >Backend Development >Golang >How to Write a Generic Function for Handling Structs with Common Members from an External Package in Go?
Writing a generic function to operate on multiple structs that share common members can be challenging, especially when these structs belong to an external package. This article explores various solutions to address this scenario.
Consider a requirement to write a function that adds specific fields to Firebase message structs, including Message and MulticastMessage. Both structs contain Android and APNS fields of identical types, but they do not explicitly declare a relationship with each other.
Initially, one might attempt to define a generic interface, firebaseMessage, and implement the function as follows:
<code class="go">type firebaseMessage interface { *messaging.Message | *messaging.MulticastMessage } func highPriority[T firebaseMessage](message T) T { message.Android = &messaging.AndroidConfig{...} .... return message }</code>
However, this approach fails due to the error "message.Android undefined (type T has no field or method Android)."
A simple solution involves using a type switch to handle each specific struct type individually:
<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>
This works effectively if the number of types in the union is limited.
If accessing the common members is essential, one approach is to create a wrapper struct with a common method that can be called by all structs in the union. The drawback is that multiple wrapper structs must be created for different types:
<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>
For situations with numerous structs, reflection can be a more appropriate solution.
<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>
Note that since this approach uses reflection, it is essential to ensure that the fields are addressable.
Depending on the specific requirements, the appropriate solution can vary significantly. This article provides several viable options for handling such scenarios in Go.
The above is the detailed content of How to Write a Generic Function for Handling Structs with Common Members from an External Package in Go?. For more information, please follow other related articles on the PHP Chinese website!