Reflection Basics
Method Lookup
Reflection can check whether a type exposes a named method.
methods
Use method lookup for inspection and adapters, but keep normal code paths explicit when possible.
Method Lookup
method_lookup.go
Replay: real traced execution (multi-file project)
package main
import (
"fmt"
"reflect"
)
type Report struct {
Title string
}
func (r Report) Summary() string {
return "report:" + r.Title
}
func main() {
var methodName = "Summary"
reportType := reflect.TypeOf(Report{})
method, ok := reportType.MethodByName(methodName)
methodType := "none"
if ok {
methodType = method.Type.String()
}
fmt.Println("method_name=", methodName)
fmt.Println("found=", ok)
fmt.Println("method_count=", reportType.NumMethod())
fmt.Println("method_type=", methodType)
}
package main
import (
"fmt"
"reflect"
)
type Report struct {
Title string
}
func (r Report) Summary() string {
return "report:" + r.Title
}
func main() {
var methodName = "Missing"
reportType := reflect.TypeOf(Report{})
method, ok := reportType.MethodByName(methodName)
methodType := "none"
if ok {
methodType = method.Type.String()
}
fmt.Println("method_name=", methodName)
fmt.Println("found=", ok)
fmt.Println("method_count=", reportType.NumMethod())
fmt.Println("method_type=", methodType)
}
methodName ← "Summary", reportType ← &reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:10681, PtrToThis:64032}}
16func main() {17 var methodName→ "Summary" = "Summary" //@methodName="Missing"18 reportType→ &reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:10681, PtrToThis:64032}} := reflect.TypeOf(Report{})19 method→ reflect.Method{Name:"Summary", PkgPath:"", Type:(*reflect.rtype)(⟨addr D⟩), Func:reflect.Value{typ_:(*abi.Type)(⟨addr D⟩), ptr:(unsafe.Pointer)(⟨addr E⟩), flag:0x13}, Index:0}, ok→ true := reportType&reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:10681, PtrToThis:64032}}.MethodByName(methodName"Summary")20 methodType→ "none" := "none"21 if ok {methodType ← "func(main.Report) string"
20methodType := "none"21if oktrue {22 methodType→ "func(main.Report) string" = method.Type&reflect.rtype{t:abi.Type{Size_:0x8, PtrBytes:0x8, Hash:⟨addr F⟩, TFlag:0x0, Align_:0x8, FieldAlign_:0x8, Kind_:0x33, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(nil), GCData:(*uint8)(⟨addr C⟩), Str:-8, PtrToThis:0}}.String()23}fmt.Println("method_name=", methodName)
25 fmt.Println("method_name=", methodName"Summary")26 fmt.Println("found=", oktrue)27 fmt.Println("method_count=", reportType&reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:10681, PtrToThis:64032}}.NumMethod())28 fmt.Println("method_type=", methodType"func(main.Report) string")29}outputmethod_name= Summary found= true method_count= 1 method_type= func(main.Report) string
methodName ← "Missing", reportType ← &reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:10681, PtrToThis:64032}}
16func main() {17 var methodName→ "Missing" = "Missing"18 reportType→ &reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:10681, PtrToThis:64032}} := reflect.TypeOf(Report{})19 method→ reflect.Method{Name:"", PkgPath:"", Type:reflect.Type(nil), Func:reflect.Value{typ_:(*abi.Type)(nil), ptr:(unsafe.Pointer)(nil), flag:0x0}, Index:0}, ok→ false := reportType&reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:10681, PtrToThis:64032}}.MethodByName(methodName"Missing")20 methodType→ "none" := "none"21 if ok {22 methodType = method.Type.String()23 }2425 fmt.Println("method_name=", methodName"Missing")26 fmt.Println("found=", okfalse)27 fmt.Println("method_count=", reportType&reflect.rtype{t:abi.Type{Size_:0x10, PtrBytes:0x8, Hash:⟨addr A⟩, TFlag:0x7, Align_:0x8, FieldAlign_:0x8, Kind_:0x19, Equal:(func(unsafe.Pointer, unsafe.Pointer) bool)(⟨addr B⟩), GCData:(*uint8)(⟨addr C⟩), Str:10681, PtrToThis:64032}}.NumMethod())28 fmt.Println("method_type=", methodType"none")29}outputmethod_name= Missing found= false method_count= 1 method_type= none