Tuesday, April 22, 2025
HomeGolangReflecting on Weak Pointers: A Proposal for reflect-Primarily based Weak Pointer Creation...

Reflecting on Weak Pointers: A Proposal for reflect-Primarily based Weak Pointer Creation – Getting Assist


With the introduction of weak pointers in Go 1.24, I’ve been exploring their use circumstances. I’ve discovered a state of affairs the place I have to create and handle weak pointers dynamically, primarily based on sorts decided at runtime – primarily, I would like reflection capabilities for weak pointers.

The present weak.Pointer is generic, and so far as I can inform, Go doesn’t at present help calling generic capabilities through reflection. This makes it unimaginable to create a weak.Pointer[T] when T is barely generally known as a mirror.Sort.

I’ve appeared via the difficulty tracker and the golang-nuts mailing listing, and I haven’t discovered any current discussions instantly addressing this. Earlier than I submit a proper proposal on GitHub, I wished to gauge the group’s opinion on whether or not including reflection help for weak pointers can be a precious addition to the language.

Right here’s a tough sketch of what I envision the API would possibly seem like (utilizing a hypothetical weak.PointerAny):
bundle weak // or maybe a brand new bundle like mirror/weak

sort PointerAny struct {
	typ mirror.Sort
	u   unsafe.Pointer
}

func MakeAny(ptr any) PointerAny {
	ptr = abi.Escape(ptr)
	v := mirror.ValueOf(ptr)
	t := v.Sort()
	if t.Form() != mirror.Pointer {
		panic("ptr just isn't a pointer")
	}
	var u unsafe.Pointer
	if ptr != nil {
		u = runtime_registerWeakPointer(v.UnsafePointer())
	}
	runtime.KeepAlive(ptr)
	return PointerAny{typ: t.Elem(), u: u}
}

func (p PointerAny) Worth() any {
	if p.u == nil {
		return nil
	}
	ptr := runtime_makeStrongFromWeak(p.u)
	if ptr == nil {
		return nil
	}
	return mirror.NewAt(p.typ, ptr).Interface()
}

This PointerAny would enable making a weak pointer from an any (which have to be a pointer) and retrieving the unique worth as an any.

Is there a compelling cause to not add this? Would including reflection help for weak pointers introduce important complexity or have unintended penalties? Maybe there are basic explanation why this hasn’t been carried out already.

I’m keen to listen to your ideas. Thanks!

IMHO, weak pointer doesn’t have to know the precise sort of the worth. Replicate is at all times very expensive and I doubt it’s a standard use. You’ll be able to at all times merely add your individual wrapper round weak pointer with its sort:

sort MyPointer struct {
    t mirror.Sort
    p weak.Pointer
}

That wrapper doesn’t resolve the generic sort challenge for reflection. I nonetheless get the can't use generic sort weak.Pointer[T any] with out instantiation error.

Yeah, as a result of reflection and generics function in numerous fields. One is for comptime one other is for runtime. You can even attempt to create pointer to any worth and go it to weak pointer creation, one thing like:

func Pointer[T any](val T) *T {
	v := mirror.ValueOf(val)
	if !v.CanAddr() {
		v = mirror.ValueOf(&val)
	}

	ptr, okay := v.Interface().(*T)
	if !okay {
		panic("")
	}

	return ptr
}

I have to name a Make generic perform to create weak pointers once I solely have a mirror.Worth, which isn’t attainable with the present code. It would look one thing like this:

func MakeAny(ptr any) PointerAny

For those who imply bypassing the kind like this, it’s going to trigger an inside error.

func MakeAny(ptr any) weak.Pointer[struct{}] {
	return weak.Make((*struct{})(mirror.ValueOf(ptr).UnsafePointer()))
}

You want a worth to be a pointer to deduce its sort. And I meant one thing like this:

bundle most important

import (
	"fmt"
	"mirror"
	"weak"
)

func Pointer[T any](val T) *T {
	v := mirror.ValueOf(val)
	if !v.CanAddr() {
		v = mirror.ValueOf(&val)
	}

	ptr, okay := v.Interface().(*T)
	if !okay {
		panic("")
	}

	return ptr
}

func most important() {
	i := 5
	p := weak.Make(Pointer(i))
	fmt.Println(*p.Worth()) // Output: 5
}

I would like to make use of weak pointers on this state of affairs.

bundle most important

import (
    "fmt"
    "mirror"
)

sort WeaKPointer struct{}

func MakeAny(ptr any) WeaKPointer {
    panic("not carried out")
}

func (p WeaKPointer) Worth() any {
    panic("not carried out")
}

var cases = make(map[string]WeaKPointer)

// ExampleFunc creates a weak pointer for all pointer sorts within the struct and saves them to the worldwide variable cases.
// This perform known as by others in a library, and we can't know the kind of T prematurely.
func ExampleFunc[T any](val T) {
    rfType := mirror.TypeOf(val)
    rfValue := mirror.ValueOf(val)
    if rfType.Form() != mirror.Struct {
        panic("T have to be a struct")
    }
    for i := 0; i < rfType.NumField(); i++ {
        typeField := rfType.Discipline(i)
        valueField := rfValue.Discipline(i)
        if typeField.Sort.Form() == mirror.Pointer {
            cases[typeField.Name] = MakeAny(valueField.Interface())
        }
    }
}

sort Struct1 struct {
    Field1 *int
    Field2 *string
}

func most important() {
    s1 := Struct1{
        Field1: new(int),
        Field2: new(string),
    }
    ExampleFunc(s1)
    fmt.Println(cases)
}

bundle most important

import (
	"fmt"
	"mirror"
	"weak"
)

var cases = make(map[string]weak.Pointer[reflect.Value], 0)

// ExampleFunc creates a weak pointer for all pointer sorts within the struct and saves them to the worldwide variable cases.
// This perform known as by others in a library, and we can't know the kind of T prematurely.
func ExampleFunc[T any](val T) {
	rfType := mirror.TypeOf(val)
	rfValue := mirror.ValueOf(val)
	if rfType.Form() != mirror.Struct {
		panic("T have to be a struct")
	}

	for i := 0; i < rfType.NumField(); i++ {
		typeField := rfType.Discipline(i)
		valueField := rfValue.Discipline(i)
		if typeField.Sort.Form() == mirror.Pointer {
			cases[typeField.Name] = weak.Make(&valueField)
		}
	}
}

sort Struct1 struct {
	Field1 *int
	Field2 *string
}

func most important() {
	s1 := Struct1{
		Field1: new(int),
		Field2: new(string),
	}
	*s1.Field1 = 5
	*s1.Field2 = "check"
	ExampleFunc(s1)
	for n, v := vary cases {
		fmt.Println(n, v.Worth())
	}
}

Right here, Make solely creates weak tips to mirror.Worth, not weak tips to the kind itself.

bundle most important

import (
	"fmt"
	"mirror"
	"runtime"
	"weak"
)

var cases = make(map[string]weak.Pointer[reflect.Value], 0)

// ExampleFunc creates a weak pointer for all pointer sorts within the struct and saves them to the worldwide variable cases.
// This perform known as by others in a library, and we can't know the kind of T prematurely.
func ExampleFunc[T any](val T) {
	rfType := mirror.TypeOf(val)
	rfValue := mirror.ValueOf(val)
	if rfType.Form() != mirror.Struct {
		panic("T have to be a struct")
	}

	for i := 0; i < rfType.NumField(); i++ {
		typeField := rfType.Discipline(i)
		valueField := rfValue.Discipline(i)
		if typeField.Sort.Form() == mirror.Pointer {
			cases[typeField.Name] = weak.Make(&valueField)
		}
	}
}

sort Struct1 struct {
	Field1 *int
	Field2 *string
}

func most important() {

	s1 := Struct1{
		Field1: new(int),
		Field2: new(string),
	}
	*s1.Field1 = 5
	*s1.Field2 = "check"
	ExampleFunc(s1)

	runtime.GC()

	for n, v := vary cases {
		fmt.Println(n, v.Worth())
		if v.Worth() == nil {
			panic(fmt.Sprintf("%v shouldn't be nil", n))
		}
	}

	runtime.KeepAlive(s1)
	*s1.Field1 = 10
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments