Skip to content

Instantly share code, notes, and snippets.

@williballenthin
Last active August 29, 2022 22:14
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save williballenthin/ee0335a6826ce55ece2d to your computer and use it in GitHub Desktop.
Save williballenthin/ee0335a6826ce55ece2d to your computer and use it in GitHub Desktop.
Methods for fetching structure fields in Go (golang)
package main
import "log"
import "time"
import "reflect"
// suggested via http://stackoverflow.com/a/8363629/87207
func trace(s string) (string, time.Time) {
log.Println("START:", s)
return s, time.Now()
}
// suggested via http://stackoverflow.com/a/8363629/87207
func un(s string, startTime time.Time) {
endTime := time.Now()
log.Println(" END:", s, "ElapsedTime in seconds:", endTime.Sub(startTime))
}
type S struct {
A int
B int
C int
D int
E int
F int
G int
H int
X int
Y int
}
type Getter func(*S, string) int
// get a field by static offset
func getField(s *S, _ string) int {
return s.X
}
// dynamically lookup a field
// 40x slower than getField()
func reflectField(s *S, field string) int {
r := reflect.ValueOf(s)
f := reflect.Indirect(r).FieldByName(field)
return int(f.Int())
}
// create a function that knows what slot to fetch given a name.
// 10x slower than getField()
func makeFieldGetter(v reflect.Value, field string) Getter {
t := v.Type()
for i := 0; i < v.NumField(); i++ {
if t.Field(i).Name == field {
return func(s *S, _ string) int {
av := reflect.ValueOf(s).Elem()
i, _ := av.Field(i).Interface().(int)
return i
}
}
}
return nil
}
func testMethod(name string, s *S, f Getter) {
defer un(trace(name))
for i := 0; i < 10 * 1000 * 1000; i++ {
x := f(s, "X")
x = x
}
}
func main() {
s := S{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
testMethod("direct", &s, getField)
testMethod("getter", &s, makeFieldGetter(reflect.ValueOf(&s).Elem(), "X"))
testMethod("reflect", &s, reflectField)
}
@williballenthin
Copy link
Author

results

» go build && ./reflector                                       
2015/06/09 22:51:07 START: direct
2015/06/09 22:51:08   END: direct ElapsedTime in seconds: 50.241986ms
2015/06/09 22:51:08 START: getter
2015/06/09 22:51:08   END: getter ElapsedTime in seconds: 464.712541ms
2015/06/09 22:51:08 START: reflect
2015/06/09 22:51:10   END: reflect ElapsedTime in seconds: 2.416859844s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment