Home >Backend Development >Golang >How to Create a Non-Nil Object of a Typed Value in Go 1.18 Generics?

How to Create a Non-Nil Object of a Typed Value in Go 1.18 Generics?

Patricia Arquette
Patricia ArquetteOriginal
2024-12-10 08:11:12146browse

How to Create a Non-Nil Object of a Typed Value in Go 1.18 Generics?

Create New Object of Typed Value via Go (go 1.18) Generics

When working with generics in Go 1.18, you may encounter a situation where you need to create a new instance of a custom type within a generic function. The following problem demonstrates this challenge:

Problem

In the provided code example, the Create function in the FruitFactory struct is intended to create a new instance of type T, but it currently returns nil. This results in a segmentation fault when attempting to access attributes of the object.

type FruitFactory[T any] struct{}

func (f FruitFactory[T]) Create() *T {
    // How to create non-nil fruit here?
    return nil
}

type Apple struct {
    color string
}

func example() {
    appleFactory := FruitFactory[Apple]{}
    apple := appleFactory.Create()
    // Panics because nil pointer access
    apple.color = "red"
}

Solution

To resolve the issue, we need to modify the Create function to return a valid instance of type T. There are two approaches to achieve this:

Approach 1 (Non-Pointer Types)

If the custom type is not a pointer type (like the Apple struct), you can declare a typed variable and return its address:

func (f FruitFactory[T]) Create() *T {
    var a T
    return &a
}

Approach 2 (Pointer Types)

If the custom type is a pointer type (like *Apple), the solution is more involved. You can leverage the power of type inference to constrain the type of the factory to pointer types:

// Constraining a type to its pointer type
type Ptr[T any] interface {
    *T
}

// The first type param will match pointer types and infer U
type FruitFactory[T Ptr[U], U any] struct{}

func (f FruitFactory[T,U]) Create() T {
    // Declare var of non-pointer type. This is not nil!
    var a U
    // Address it and convert to pointer type (still not nil)
    return T(&a)
}

type Apple struct {
    color string
}

func example() {
    // Instantiating with ptr type
    appleFactory := FruitFactory[*Apple, Apple]{}
    apple := appleFactory.Create()

    // All good
    apple.color = "red"

    fmt.Println(apple) // &{red}
}

Note: For Approach 2, type inference has been disabled in Go 1.18, so you must manually specify all type parameters, such as: FruitFactory[*Apple, Apple]{}.

With these modifications, the Create function will return a valid instance of type T (or *T), allowing you to access its attributes without causing segmentation faults.

The above is the detailed content of How to Create a Non-Nil Object of a Typed Value in Go 1.18 Generics?. 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