Generic Use in Unmarshal (Go 1.18)
When utilizing generics in Go 1.18, such as creating a container to hold various report types, type constraints can arise. Consider the following setup:
You may encounter challenges with type constraints on return types, leading to "freetext semantics" in the GetBody() function to accommodate type assertion.
Challenges and Solutions
The issue stems from Go not supporting type assertions for structs and not allowing pointers to generic types. To address this, you can create an interface that implements Getters for the LocationID, Provider, ReportType, and Body. However, this solution requires sacrificing type safety.
A safer approach involves forgoing parametric polymorphism and utilizing a concrete switch statement based on the discriminator value during JSON unmarshalling. This ensures that the correct concrete type is used for each report type.
Alternative Approach
For dynamic JSON parsing, you can employ a generic unmarshal function:
<code class="go">func unmarshalAny[T any](bytes []byte) (*T, error) { out := new(T) if err := json.Unmarshal(bytes, out); err != nil { return nil, err } return out, nil }</code>
While this function offers flexibility, it is essential to note that if its implementation is minimal, it merely performs the same actions as inlining the unmarshalling logic directly. Thus, using this function is only justified if it introduces additional logic.
In summary, carefully consider the necessity of generics when working with concrete types and JSON unmarshalling. Opt for a switch-based solution when necessary without compromising type safety, and exercise caution when employing generic functions that unnecessarily duplicate functionality.
The above is the detailed content of How Can I Safely Unmarshal JSON with Generic Types in Go 1.18?. For more information, please follow other related articles on the PHP Chinese website!