如何正确检查plugin.Open返回的错误类型

I would like to know how can I check the type of error returned by plugin.Open, e.g:

package main

import "plugin"

func main() {
  _, err := plugin.Open("./module.so")
  // here
}

I would like to do something different if the error is:

plugin.Open("./module.so"): realpath failed

Which basically means that the file doesn't exist.

Example of desired result:

package main

import "plugin"

func main() {
  _, err := plugin.Open("./module.so")
  if err.Error() == "plugin.Open(\"./module.so\"): realpath failed" {
    // do something different here
  } else {
    log.Fatal(err)
  }
}

The string that I pass to plugin.Open can have other values, so it needs to be something more smart than that.

Thanks in advance.

Inspection of the code for plugin.Open() reveals the package calls out to some C code to determine whether the path exists. If it doesn't, it returns a plain error value. In particular, the package does not define any sentinel errors which you can compare against, nor does it return its own concrete implementer of the error interface which carries custom metadata. This is the code which produces that error:

return nil, errors.New(`plugin.Open("` + name + `"): realpath failed`)

errors.New is a basic implementation of the error interface which doesn't allow any additional information to be passed. Unlike other locations in the standard library which return errors (such as path non-existent errors from the os package), you can't get such metadata in this instance.


Check whether the module file exists first

My preference would be to verify whether the module exists before attempting to load it, using the native capabilities provided by the os package:

modulePath := "./module.so"
if _, err := os.Stat(modulePath); os.IsNotExist(err) {
    // Do whatever is required on module not existing
}

// Continue to load the module – can be another branch of the if block
// above if necessary, depending on your desired control flow.

Compare a subset of the error values

You could also use strings.Contains to search for the value realpath failed in the returned error value. This is not a good idea in the event that string changes in future, so if you adopt this pattern, at the very least you should ensure you have rigorous tests around it (and even then it's still not great).

_, err := plugin.Open("./module.so")
if err != nil {
    if strings.Contains(err.Error(), "realpath failed") {
        // Do your fallback behavior for module not existing
        log.Fatalf("module doesn't exist")
    } else {
        // Some other type of error
        log.Fatalf("%+v", err)
    }
}