-
Notifications
You must be signed in to change notification settings - Fork 18k
reflect: MakeStruct #5748
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
sure (actually, for consistency with other functions in 'reflect', let's call it StructOf): func StructOf(name string, fields []StructField) Type this would generate a reflect.structType with the correct field names, offsets and alignment informations. each field in []StructField would not need to be completely initialized ie: only StructField.Name and StructField.Type would be mandatory or perhaps introduce a new struct Field with only those mandatory informations and use that instead of StructField ? -s |
Thanks. IIUC, one would not be able to directly reference any field of the run-time defined struct, like in 'InstanceName.FieldName', because the type is not known at compile time. The fields would be gettable/settable only through reflect again. I don't think Go needs such functionality. If eg., as you wrote, precise binary layout is required by a non Go library, I think some C glue should be written instead. That's fast and accessible in both of the worlds. Abusing reflection for run-time type-unsafe bypassing of tasks which can be type-safely handled at compile time seems like a bad idea to me. |
Labels changed: added priority-later, removed priority-triage. Owner changed to @rsc. |
Comment 11 by [email protected]: It would be very useful for my current project to be able to create structs type objects from a type description at runtime. |
Here is a patch for this. I'm new to compiler foo so It would be good if someone could if someone could check this over. Especially the field alignment and GC. Attachments:
|
Thanks for working on this. Please submit patches through the process described at http://golang.org/doc/contribute.html. Thanks. I think that the comparison algorithm isn't quite right. I don't think it will work for struct { a, b string }. |
I agree this would be a useful feature for programs that create a graph of compact objects based on a dynamically loaded schema, e.g. a .proto file or XML schema, or the stack frames of an interpreter. 0xjnml: it needn't be type-unsafe. So long as MakeStruct rejects structs whose fields overlap, you can't create pointer/uintptr union types. MakeStruct should probably also reject anonymous fields, since the resulting struct could have a non-empty method-set but would have compiler-generated wrapper methods for them. |
I see Carl did some additional work here: https://code.google.com/r/carlchatfield-go-arrayof-structof/source/list Could I ask: Carl, where does this stand? Is it done? I tried the above patch from Mar 2, made it work with a little adaptation. I think I'm seeing the string-comparison issue that Ian pointed out. For example this test fails (below). I'm not sure why it fails or how to fix it (any insight Ian--what was your observation?) Just wanted to ask where things stood with Carls' work and get everyone else's input on where things stand. Is development on this going on elsewhere? Thanks. Jason // failing test: package main import ( "fmt" "reflect" "testing" ) func TestStructOfTwoStrings(t *testing.T) { => st := reflect.StructOf([]reflect.StructField{{Name: "a", Type: reflect.TypeOf("")}, {Name: "b", Type: reflect.TypeOf("")}}) v1 := reflect.New(st).Elem() v2 := reflect.New(st).Elem() i1 := v1.Interface() i2 := v2.Interface() if i1 != i2 { fmt.Printf("constructed struct %v not equal to itself", v1.Interface()) panic("but it should be!") } v1.FieldByName("a").Set(reflect.ValueOf("hello")) if i1, i2 := v1.Interface(), v2.Interface(); i1 == i2 { fmt.Printf("constructed structs %v and %v should not be equal", i1, i2) panic("but they were!") } v2.FieldByName("a").Set(reflect.ValueOf("hello")) if v1 != v2 { fmt.Printf("v1 = %#v\n", v1) fmt.Printf("v2 = %#v\n", v2) panic("v1 and v2 should be value equal now! Shouldn't they?") // currently failing here. } st = reflect.StructOf([]reflect.StructField{{Name: "X", Tag: "x", Type: reflect.TypeOf([]int(nil))}}) v1 = reflect.New(st).Elem() shouldPanic(func() { _ = v1.Interface() == v1.Interface() }) } |
My observation at the time was that the struct comparison code either did a straight memory comparison or failed to compare. But a struct with a string field requires an element by element comparison: strings are comparable, but you can't compare them using a straight memory comparison. The same is true for float, complex, interface, and structs or arrays with fields of the those types. |
CL https://golang.org/cl/101330055 mentions this issue. |
fixed by CL https://golang.org/cl/101330055 |
That CL doesn't even pass code review yet, so this issue is not fixed. |
oh. right. just ignore me :} |
ArrayOf just landed, https://go-review.googlesource.com/#/c/4111/ Getting equals and hash correct is one of the hard parts of StructOf. The ArrayOf change makes the equal and hash functions from closures. The same technique could be used here. (Closures for equal/hash became available as of https://go-review.googlesource.com/#/c/2392/) |
I'll give it a try tomorrow. |
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: implement StructOf - reflect: tests for StructOf - runtime: generate typelinks for structs Fixes golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: implement StructOf - reflect: tests for StructOf - runtime: generate typelinks for structs Fixes golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: implement StructOf - reflect: tests for StructOf - runtime: generate typelinks for structs Fixes golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
CL https://golang.org/cl/9251 mentions this issue. |
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: implement StructOf - reflect: tests for StructOf - runtime: generate typelinks for structs Fixes golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: implement StructOf - reflect: tests for StructOf - runtime: generate typelinks for structs Fixes golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: implement StructOf - reflect: tests for StructOf Fixes golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: implement StructOf - reflect: tests for StructOf Fixes golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: first stab at implementing StructOf - reflect: tests for StructOf Creating struct types with embedded interfaces with unexported methods is not supported yet and will panic. Updates golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: first stab at implementing StructOf - reflect: tests for StructOf Creating struct types with embedded interfaces with unexported methods is not supported yet and will panic. Binaries' sizes for linux_amd64: old=tip (0104a31) old bytes new bytes delta bin/go 9911336 9915456 +0.04% reflect 781704 830048 +6.18% Updates golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: first stab at implementing StructOf - reflect: tests for StructOf Creating struct types with embedded interfaces with unexported methods is not supported yet and will panic. Binaries' sizes for linux_amd64: old=tip (0104a31) old bytes new bytes delta bin/go 9911336 9915456 +0.04% reflect 781704 830048 +6.18% Updates golang#5748. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44
This change exposes a facility to create new struct types from a slice of reflect.StructFields. - reflect: first stab at implementing StructOf - reflect: tests for StructOf StructOf creates new struct types in the form of structTypeWithMethods to accomodate the GC (especially the uncommonType.methods slice field.) Creating struct types with embedded interfaces with unexported methods is not supported yet and will panic. Creating struct types with non-ASCII field names or types is not yet supported (see #15064.) Binaries' sizes for linux_amd64: old=tip (0104a31) old bytes new bytes delta bin/go 9911336 9915456 +0.04% reflect 781704 830048 +6.18% Updates #5748. Updates #15064. Change-Id: I3b8fd4fadd6ce3b1b922e284f0ae72a3a8e3ce44 Reviewed-on: https://go-review.googlesource.com/9251 Reviewed-by: David Crawshaw <[email protected]> Run-TryBot: David Crawshaw <[email protected]>
CL https://golang.org/cl/23170 mentions this issue. |
The initial implementation of reflect.StructOf in https://golang.org/cl/9251 had a limitation that field names had to be ASCII, which was later lifted by https://golang.org/cl/21777. Remove the out-of-date documentation disallowing UTF-8 field names. Updates: #5748 Updates: #15064 Change-Id: I2c5bfea46bfd682449c6e847fc972a1a131f51b7 Reviewed-on: https://go-review.googlesource.com/23170 Reviewed-by: David Crawshaw <[email protected]>
Is this now done? |
Seems like it. |
@ben-clayton Not completely. It's still not possible to embed types with non-exported methods. |
Or apparently recursive structs: #20013 |
@mdempsky, I think embedding types with non-exported methods should probably be a new bug rather than reusing this one for four years. |
The text was updated successfully, but these errors were encountered: