func loadPlugin(path string) (*PluginImpl, error) { ifaceType := reflect.TypeOf((*Plugin)(nil)).Elem() pluginLoad, err := plugin.Open(path) if err != nil { return nil, err } // without stubbing the fields, reflect.ValueOf(...).Elem().FieldByName(...) below will return nil newPlugin := newPluginImpl() // for each method declared in the interface, look for the same-named concrete defintion // in the loaded plugin. if that exists, find the field in the concrete implementation // instance (PluginImpl) and set each function pointer accordingly for i := 0; i < ifaceType.NumMethod(); i++ { methodName := ifaceType.Method(i).Name pluginMethod, err := pluginLoad.Lookup(methodName) if err != nil { return nil, err } implValue := reflect.ValueOf(&newPlugin).Elem() if implValue.IsZero() { return nil, fmt.Errorf("unable to get value of concrete impl") } implElem := implValue.FieldByName(methodName) if implElem.IsZero() { return nil, fmt.Errorf("unable to set value on concrete impl") } // must .Convert to the target type (implElem.Interface()), else will panic with a strangely-worded error: // "reflect.Set: value of type T is not assignable to type T" // (not a typo: the 'from' and 'to' types in the error message will be exactly the same, because // indeed if we've made it this far the types will match, hence why .Convert() succeeds!) implElem.Set(reflect.ValueOf(pluginMethod).Convert(reflect.TypeOf(implElem.Interface()))) } return &newPlugin, nil }