I'm to create an object (whatever it is) satisfying certain interface dynamically. There's no way I can do it so I'm thinking maybe I can add a func in `reflect` package to cover my need.
The `reflect.StructOf` func creates a struct type but without adding methods which gives a good example. I imitated and created an `InterfaceOf` func. However the following error appeared, ``` unexpected fault address 0xc0000b8120 fatal error: fault [signal SIGSEGV: segmentation violation code=0x2 addr=0xc0000b8120 pc=0xc0000b8120] ``` Here is the file I added into the `reflect` package, ```golang package reflect import ( "sort" "unsafe" ) type InterfaceMethod struct { Name string Func Value } func InterfaceOf(funcs []InterfaceMethod) Value { if len(funcs) == 0 { return New(TypeOf("Interface {}")) } var ( repr = []byte("struct { /* non-invertible */ }") hash = fnv1(0, []byte("struct { /* non-invertible */ }")...) size uintptr typalign uint8 methods []method ) // add sorted methods here { for idx := range funcs { if funcs[idx].Func.Type().Kind() != Func { panic("funcs contains non-func") } c := funcs[idx].Name[0] if !('A' <= c && c <= 'Z') { panic("funcs contains unexported func") } } sort.Slice(funcs, func(i, j int) bool { return funcs[i].Name < funcs[j].Name }) for idx := range funcs { ft := funcs[idx].Func.Type().common() ft.uncommon() ifn := funcs[idx].Func methods = append(methods, method{ name: resolveReflectName(newName(funcs[idx].Name, "", true)), mtyp: resolveReflectType(ft), ifn: resolveReflectText(unsafe.Pointer(&ifn)), tfn: resolveReflectText(unsafe.Pointer(&ifn)), }) } } var typ *structType var ut *uncommonType { // A *rtype representing a struct is followed directly in memory by an // array of method objects representing the methods attached to the // struct. To get the same layout for a run time generated type, we // need an array directly following the uncommonType memory. // A similar strategy is used for funcTypeFixed4, ...funcTypeFixedN. tt := New(StructOf([]StructField{ {Name: "S", Type: TypeOf(structType{})}, {Name: "U", Type: TypeOf(uncommonType{})}, {Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))}, })) typ = (*structType)(tt.Elem().Field(0).Addr().UnsafePointer()) ut = (*uncommonType)(tt.Elem().Field(1).Addr().UnsafePointer()) copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]method), methods) } ut.mcount = uint16(len(methods)) ut.xcount = ut.mcount // we only have exported methods ut.moff = uint32(unsafe.Sizeof(uncommonType{})) str := string(repr) // Round the size up to be a multiple of the alignment. size = align(size, uintptr(typalign)) // Make the struct type. var istruct any = struct{}{} prototype := *(**structType)(unsafe.Pointer(&istruct)) *typ = *prototype typ.str = resolveReflectName(newName(str, "", false)) typ.tflag = 0 // TODO: set tflagRegularMemory typ.hash = hash typ.size = size typ.ptrdata = typeptrdata(typ.common()) typ.align = typalign typ.fieldAlign = typalign typ.ptrToThis = 0 typ.tflag |= tflagUncommon { typ.kind &^= kindGCProg bv := new(bitVector) addTypeBits(bv, 0, typ.common()) if len(bv.data) > 0 { typ.gcdata = &bv.data[0] } } typ.equal = nil typ.kind &^= kindDirectIface return Zero(&typ.rtype) } ``` And a corresponding testing file, ```golang package main import ( "fmt" "reflect" "testing" ) func TestInterfaceOf(t *testing.T) { type AliceInterface interface { BobMethod() (error, string) } Alice := reflect.TypeOf((*AliceInterface)(nil)).Elem() Bob := Alice.Method(0) Carol := reflect.MakeFunc(Bob.Type, func(args []reflect.Value) []reflect.Value { fmt.Println("[wow]") nilError := reflect.Zero(reflect.TypeOf((*error)(nil)).Elem()) return []reflect.Value{nilError, reflect.ValueOf("haha")} }) Dan := reflect.InterfaceOf([]reflect.InterfaceMethod{ { Name: "BobMethod", Func: Carol, }, }) Dan.Method(0).Call([]reflect.Value{}) // panic dan := Dan.Interface().(AliceInterface) dan.BobMethod() // also panic } ``` -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/a13e8bd6-f36d-4806-aa29-748942c6d2d7n%40googlegroups.com.