Home  >  Article  >  Backend Development  >  How to Write a Generic Function for Handling Structs with Common Members from an External Package in Go?

How to Write a Generic Function for Handling Structs with Common Members from an External Package in Go?

Linda Hamilton
Linda HamiltonOriginal
2024-10-27 09:49:30949browse

How to Write a Generic Function for Handling Structs with Common Members from an External Package in Go?

Generic Function for Handling Different Structs with Common Members from External Package

Introduction

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.

Problem Definition

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.

Attempt and Error

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 = &amp;messaging.AndroidConfig{...}
    ....
    return message
}</code>

However, this approach fails due to the error "message.Android undefined (type T has no field or method Android)."

Solution 1: Type Switch

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.

Solution 2: Wrapper with Method

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>

Solution 3: Reflection

For situations with numerous structs, reflection can be a more appropriate solution.

<code class="go">func highPriority[T firebaseMessage](message T) T {
    cfg := &amp;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.

Conclusion

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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn