Home  >  Article  >  Backend Development  >  Get the type name of a generic struct without type parameters

Get the type name of a generic struct without type parameters

王林
王林forward
2024-02-13 12:27:071139browse

Get the type name of a generic struct without type parameters

In this article, php editor Strawberry will introduce to you how to get the type name of a generic structure without type parameters. Generics are a powerful programming technique that allows you to write generic code without specifying specific types. However, sometimes we may need to obtain the type name of a generic structure without containing specific type parameters. This article will answer this question in detail for you and help you better understand and apply generic programming.

Question content

Suppose I have a generic structure called foo from which I create two objects. I can determine the specific type of each using reflect.typeof() like this:

package main

import (
    "fmt"
    "reflect"
)

type foo[t any] struct {
    data t
}

func main() {
    a := foo[string]{"cheese"}
    b := foo[int]{42}

    fmt.println(reflect.typeof(a))
    fmt.println(reflect.typeof(b))
}

// main.foo[string]
// main.foo[int]

I'm interested in determining the general type of these objects (i.e. foo), rather than the specific types (i.e. foo[string] and foo[int]). Is this possible or do I need to manually extract the generic type from these strings (e.g. using regular expressions)?

edit

A regular expression might look like this:

func GetGenericType(x any) string {
    // Get type as a string
    s := reflect.TypeOf(x).String()

    // Regex to run
    r := regexp.MustCompile(`\.(.*)\[`)

    // Return capture
    return r.FindStringSubmatch(s)[1]
}


fmt.Println(GetGenericType(a))
fmt.Println(GetGenericType(b))

// foo
// foo

I also saw this question, but that didn't answer the question because it gave the specific type (i.e. main.foo[string]) instead of the generic type (i.e., foo).

Workaround

Reflection cannot see the name of a "base" generic type because the base type does not exist at runtime.

The relevant paragraph in the

go spec is Instantiation:

Instantiating a type will produce a new non-generic named type ; instantiating a function will produce a new non-generic function.

So when you write:

b := foo[int]{42}
name := reflect.typeof(b).name()

The name of this type is exactly foo[int].

It's worth noting that an identifier without a type parameter list foo is relevant at compile time, as it prevents you from redeclaring it in the same package. Type definition:

Type definition creates a new, different type with the same type The underlying type and operation are given as the type and bound Identifier, type name, give it .

typedef = identifier [ typeparameters ] type .

However, as mentioned above, instantiation results in a new named type that is different from foo; at runtime, you only deal with instantiation when you can use reflection.

In conclusion, I think your regex solution is acceptable until some helper functions are added to stdlib (if any). Reposting it here for clarity:

func getgenerictype(x any) string {
    // get type as a string
    s := reflect.typeof(x).string()

    // regex to run
    r := regexp.mustcompile(`\.(.*)\[`)

    // return capture
    return r.findstringsubmatch(s)[1]
}

Remember the difference between type.string() and type.name(): Any type can have a string representation, but only named types do name. (Obviously, right?). For example, if you write:

b := &foo[int]{42}

Then the type of b is *foo[int], which is an anonymous composite type, name() returns an empty string.

The above is the detailed content of Get the type name of a generic struct without type parameters. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete