Skip to content
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

Properly handing errors? #10

Closed
dnaeon opened this issue Jun 21, 2016 · 2 comments
Closed

Properly handing errors? #10

dnaeon opened this issue Jun 21, 2016 · 2 comments
Labels

Comments

@dnaeon
Copy link

dnaeon commented Jun 21, 2016

In Go it is a common practice to have functions, which return errors in case something went wrong, e.g. func Foo() (FooResult, error).

Doing so it is up to the caller to decide whether this is a fatal error or something that can be handled properly.

Considering the following Go code, which registers a function in Lua, what would be the best way to handle errors? Should we just panic, which would raise an exception in Lua or is there a better way to do that?

package main

import (
        "log"
        "os/user"

        "github.com/layeh/gopher-luar"
        "github.com/yuin/gopher-lua"
)

type Person struct {
        Name string
        Home string
}

func main() {
        L := lua.NewState()
        defer L.Close()

        person := L.NewTable()
        person.RawSetH(lua.LString("new"), luar.New(L, NewPerson))
        L.SetGlobal("person", person)

        if err := L.DoFile("create-person.lua"); err != nil {
                log.Fatal(err)
        }
}

func NewPerson(name string) *Person {
        user, err := user.Lookup(name)
        if err != nil {
                // How to propagate the error to Lua ??
                // panic ??
        }

        p := &Person{
                Name: name,
                Home: user.HomeDir,
        }

        return p
}

And the following example Lua code.

p = person.new("nonexisting-user")
print("username: " .. p.Name)
print("homedir: " .. p.Home)

Thanks,
Marin

@ghost
Copy link

ghost commented Jun 21, 2016

You could panic. That would mean you have to use pcall to capture the error if you want to handle it gracefully:

ok, ret = pcall(person.new, "nonexisting-user")
if not ok then
    print(ret)
else
   print("username: " .. ret.Name)
   print("homedir: " .. ret.Home)
end

Another solution is similar to how io.open operates: return the value on success, or nil and an error string on failure:

func NewPerson(name string) (*Person, string) {
        user, err := user.Lookup(name)
        if err != nil {
                return nil, err.Error()
        }

        p := &Person{
                Name: name,
                Home: user.HomeDir,
        }

        return p, ""
}
person, err = person.new("nonexisting-user")
if not person then
    print(err)
else
   print("username: " .. person.Name)
   print("homedir: " .. person.Home)
end

I prefer the latter.

@ghost ghost added the question label Jun 21, 2016
@dnaeon
Copy link
Author

dnaeon commented Jun 21, 2016

Thanks, I like the latter solution as well :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

1 participant