


How to instantiate a non-zero pointer to a type parameter using a generic Go?
php editor Xigua will introduce to you how to use non-zero pointers of generic instantiation type parameters in the Go language. In Go language, generics are a powerful feature that can increase the flexibility and reusability of code. When we need to instantiate a non-zero pointer in a generic function or method, we can use type assertions and reflection to achieve this. By using these techniques, we can create a non-zero pointer instance at runtime based on the specific type of the type parameter, thereby achieving the flexibility and versatility of generics. Let's take a closer look at the specific implementation method.
Question content
Now that type parameters are available on golang/go:master
, I decided to give it a try. It seems I've hit a limitation that I can't find in the type parameters proposal. (Or I must have missed it).
I want to write a function that returns a slice of generic type values with interface type constraints. If the type passed is an implementation with a pointer receiver, how do we instantiate it?
type SetGetter[V any] interface { Set(V) Get() V } // SetGetterSlice turns a slice of type V into a slice of type T, // with T.Set() called for each entry in values. func SetGetterSlice[V any, T SetGetter[V]](values []V) []T { out := make([]T, len(values)) for i, v := range values { out[i].Set(v) // panic if T has pointer receiver! } return out }
When the above SetGetterSlice()
function is called using the *Count
type as T
, this code will call Set(v)## Confusion occurs when #. (Go2go Playground) Not surprising since basically the code creates a slice of
nil pointers:
// Count implements SetGetter interface type Count struct { x int } func (c *Count) Set(x int) { c.x = x } func (c *Count) Get() int { return c.x } func main() { ints := []int{1, 2, 3, 4, 5} sgs := SetGetterSlice[int, *Count](ints) for _, s := range sgs { fmt.Println(s.Get()) } }
This idea doesn't work, I can't seem to find any easy way to instantiate the value pointed to.
- out[i] = new(T)
will cause compilation to fail because it returns
*T, where the type checker expects to see
T.
Calling - *new(T)
compiles but causes the same runtime panic because
new(T)returns
**Counthere In this case, the pointer to
Countis still
nil.
Changing the return type to a pointer fragment to - T
will cause compilation to fail:
func SetGetterSlice[V any, T SetGetter[V]](values []V) []*T { out := make([]*T, len(values)) for i, v := range values { out[i] = new(T) out[i].Set(v) // panic if T has pointer receiver } return out } func main() { ints := []int{1, 2, 3, 4, 5} SetGetterSlice[int, Count](ints) // Count does not satisfy SetGetter[V]: wrong method signature }
The only solution I've found so far is to require that the constructor be passed to a generic function. But it feels wrong and a bit boring. If
func F(T interface{})() []T is perfectly valid syntax, why is this needed?
func SetGetterSlice[V any, T SetGetter[V]](values []V, constructor func() T) []T { out := make([]T, len(values)) for i, v := range values { out[i] = constructor() out[i].Set(v) } return out } // ... func main() { ints := []int{1, 2, 3, 4, 5} SetGetterSlice[int, *Count](ints, func() *Count { return new(Count) }) }
My questions (in order of priority):
- Am I overlooking something obvious?
- Is this a limitation of generics in Go? Is this as good as it gets?
- Is this limitation known or should I raise an issue in the Go project?
T convertible to its pointer type. In its most basic form, the technique looks like this (with anonymous constraints):
func Foo[T any, PT interface { *T; M() }]() { p := PT(new(T)) p.M() // calling method on non-nil pointer }
https://www.php.cn/link/24aef8cb3281a2422a59b51659f1ad2e
<小时>Step-by-step solution
Your constraintsSetGetter already declare the type parameter
V, so we modify the above example slightly:
// V is your original type param // T is the additional helper param type SetGetter[V any, T any] interface { Set(V) Get() V *T }
SetGetterSlice function, whose type parameter is
T any, whose purpose is only to instantiate the constraint
SetGetter.
&out[i] to a pointer type and successfully call the method on the pointer receiver:
// T is the type with methods with pointer receiver // PT is the SetGetter constraint with *T func SetGetterSlice[V any, T any, PT SetGetter[V, T]](values []V) []T { out := make([]T, len(values)) for i, v := range values { // out[i] has type T // &out[i] has type *T // PT constraint includes *T p := PT(&out[i]) // valid conversion! p.Set(v) // calling with non-nil pointer receiver } return out }
CFE57E536C89530D9A8C38E10967A10D
This becomes more verbose becauseSetGetterSlice The above is the detailed content of How to instantiate a non-zero pointer to a type parameter using a generic Go?. For more information, please follow other related articles on the PHP Chinese website! now requires three type parameters: the original
V plus
T (the type with the pointer receiver) and
PT (new constraints). However, when you call the function, you can omit the third - via type inference, the type parameters
V and ## required to instantiate
PT SetGetter[V,T] #T
are all known:
SetGetterSlice[int, Count](ints)

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

There are many ways to center Bootstrap pictures, and you don’t have to use Flexbox. If you only need to center horizontally, the text-center class is enough; if you need to center vertically or multiple elements, Flexbox or Grid is more suitable. Flexbox is less compatible and may increase complexity, while Grid is more powerful and has a higher learning cost. When choosing a method, you should weigh the pros and cons and choose the most suitable method according to your needs and preferences.

The calculation of C35 is essentially combinatorial mathematics, representing the number of combinations selected from 3 of 5 elements. The calculation formula is C53 = 5! / (3! * 2!), which can be directly calculated by loops to improve efficiency and avoid overflow. In addition, understanding the nature of combinations and mastering efficient calculation methods is crucial to solving many problems in the fields of probability statistics, cryptography, algorithm design, etc.

The Y-axis position adaptive algorithm for web annotation function This article will explore how to implement annotation functions similar to Word documents, especially how to deal with the interval between annotations...

How to elegantly handle the spacing of Span tags after a new line In web page layout, you often encounter the need to arrange multiple spans horizontally...

How to make the height of adjacent columns of the same row automatically adapt to the content? In web design, we often encounter this problem: when there are many in a table or row...

SQLSELECT statement Detailed explanation SELECT statement is the most basic and commonly used command in SQL, used to extract data from database tables. The extracted data is presented as a result set. SELECT statement syntax SELECTcolumn1,column2,...FROMtable_nameWHEREconditionORDERBYcolumn_name[ASC|DESC]; SELECT statement component selection clause (SELECT): Specify the column to be retrieved. Use * to select all columns. For example: SELECTfirst_name,last_nameFROMemployees; Source clause (FR

std::unique removes adjacent duplicate elements in the container and moves them to the end, returning an iterator pointing to the first duplicate element. std::distance calculates the distance between two iterators, that is, the number of elements they point to. These two functions are useful for optimizing code and improving efficiency, but there are also some pitfalls to be paid attention to, such as: std::unique only deals with adjacent duplicate elements. std::distance is less efficient when dealing with non-random access iterators. By mastering these features and best practices, you can fully utilize the power of these two functions.

There are four ways to adjust the WordPress article list: use theme options, use plugins (such as Post Types Order, WP Post List, Boxy Stuff), use code (add settings in the functions.php file), or modify the WordPress database directly.
