Created
February 5, 2023 22:21
-
-
Save edfletcher/ffbf99622dbef6e616fb75c0ce787059 to your computer and use it in GitHub Desktop.
loadPlugin.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment