reflectx

package
v0.0.0-...-c25df61 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 12, 2026 License: MIT Imports: 3 Imported by: 2

Documentation

Overview

Package reflectx provides extensions to the reflect package

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CopyInterface

func CopyInterface[I any](value I) (ptr I, mutable bool)

CopyInterface returns a new copy of the interface value I. I must be an interface type.

value is a copy of value, mutable indicates if the value is mutable, i.e. if it is backed by a pointer type.

If value is backed by a pointer type, the pointed-to-value is copied, and a pointer to that copy and the boolean true is returned. If the value is not backed by a non-pointer type C, and *C implements I, then a pointer to the copy of the underlying value, along with the boolean true, is returned. Otherwise, a simple copy, and the boolean false, is returned.

Example (Lift)
package main

import (
	"fmt"

	"go.tkw01536.de/pkglib/reflectx"
)

// counter is used for testing.
//
//nolint:recvcheck // testing code
type counter struct {
	Value int
}

func (c *counter) Inc() {
	c.Value++
}

func (c counter) AsInt() int {
	return c.Value
}

func main() {
	// AsInt is an interface that returns an integer value
	type AsInt interface {
		AsInt() int
	}

	// make a *non-pointer* counter
	original := AsInt(counter{Value: 0})

	// make a cp and increment the cp
	cp, _ := reflectx.CopyInterface(original)
	cp.(interface{ Inc() }).Inc()

	// print the original value and the new value
	// the original is a plain value, the copy is a pointer!
	fmt.Println("original counter", original)
	fmt.Println("copy of counter", cp)

}
Output:

original counter {0}
copy of counter &{1}
Example (Pointer)
package main

import (
	"fmt"

	"go.tkw01536.de/pkglib/reflectx"
)

// counter is used for testing.
//
//nolint:recvcheck // testing code
type counter struct {
	Value int
}

func (c *counter) Inc() {
	c.Value++
}

func (c counter) AsInt() int {
	return c.Value
}

func main() {
	// Inc is an interface that increments
	type Inc interface {
		Inc()
	}

	// make a pointer to a counter
	original := Inc(&counter{Value: 0})

	// make a cp and increment the cp
	cp, _ := reflectx.CopyInterface(original)
	cp.Inc()

	// print the value of the original counter and the copy
	// the copy is also a pointer
	fmt.Println("original counter", original)
	fmt.Println("copy of counter", cp)

}
Output:

original counter &{0}
copy of counter &{1}

func IterAllFields

func IterAllFields(typ reflect.Type) iter.Seq2[reflect.StructField, []int]

IterateAllFields iterates over the struct fields of typ and their indexes. Fields are iterated in the order they are returned by reflect.Field().

When typ is not a struct type, IterAllFields panics. When typ contains an embedded struct, calls IterAllFields recursively.

Unlike IterFields, this function recurses into embedded structs. See also IterFields.

Example

Iterate over the fields of a struct.

package main

import (
	"fmt"
	"reflect"

	"go.tkw01536.de/pkglib/reflectx"
)

func main() {
	type Embed struct {
		EmbeddedField string // field in an embedded struct
	}

	type SomeStruct struct {
		Field string // regular field
		//lint:ignore U1000 // false positive: used by TypeFor call below
		string         // embedded non-struct, not called recursively
		Embed          // an embed
		Another string // another field
	}

	for f, index := range reflectx.IterAllFields(reflect.TypeFor[SomeStruct]()) {
		fmt.Println("encountered field", f.Name, "with index", index)
	}

}
Output:

encountered field Field with index [0]
encountered field string with index [1]
encountered field EmbeddedField with index [2 0]
encountered field Another with index [3]

func IterFields

func IterFields(typ reflect.Type) iter.Seq2[reflect.StructField, int]

IterFields returns an iterator that iterates over the struct fields of typ in the order they are returned by reflect.Field.

When typ is not a struct type, IterFields panics. Unlike IterAllFields, does not iterate over embedded fields recursively.

Example

Iterate over the fields of a struct.

package main

import (
	"fmt"
	"reflect"

	"go.tkw01536.de/pkglib/reflectx"
)

func main() {
	type Embed struct {
		EmbeddedField string // field in an embedded struct
	}

	type SomeStruct struct {
		Field string // regular field
		//lint:ignore U1000 // false positive: used by TypeFor below
		string         // embedded non-struct, not called recursively
		Embed          // an embed
		Another string //
	}

	for f, index := range reflectx.IterFields(reflect.TypeFor[SomeStruct]()) {
		fmt.Println("encountered field", f.Name, "with index", index)
	}

}
Output:

encountered field Field with index 0
encountered field string with index 1
encountered field Embed with index 2
encountered field Another with index 3
Example (Early)

Iterate over the fields of a struct, stopping early.

package main

import (
	"fmt"
	"reflect"

	"go.tkw01536.de/pkglib/reflectx"
)

func main() {
	type Embed struct {
		EmbeddedField string // field in an embedded struct
	}

	type SomeStruct struct {
		Field string // regular field
		//lint:ignore U1000 // false positive: used by TypeFor below
		string         // embedded non-struct, not called recursively
		Embed          // an embed
		Another string //
	}

	for f, index := range reflectx.IterFields(reflect.TypeFor[SomeStruct]()) {
		fmt.Println("encountered field", f.Name, "with index", index)
		break
	}

}
Output:

encountered field Field with index 0

func NameOf

func NameOf(typ reflect.Type) string

NameOf returns the fully qualified name for typ.

A fully qualified name consists of the package path, followed by a ".", followed by the type name. Builtin types have the empty package path. Types that are not named return the empty string.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL