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

Linda Hamilton
Release: 2024-10-27 09:49:30
Original
958 people have browsed it

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>
Copy after login

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>
Copy after login

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>
Copy after login

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>
Copy after login

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!

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!