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.
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)?
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
).
Reflection cannot see the name of a "base" generic type because the base type does not exist at runtime.
The relevant paragraph in thego 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!