Repository: bmatsuo/lmdb-go
Pull request #73 (2016-04-12 07:55:58)

lmdb: remove direct dependency on the fmt package
It was only being used in a couple places (outside of tests).  So
existing trivial usages of Errorf were replaced with errors.New and the
OpError.Error method was rewritten to use string concatenation, which
ends up being faster and using fewer allocations.  Though in practice
the performance of error message serialization is not going to impact an
application in a stable production environment.


Patch:
diff --git a/lmdb/env.go b/lmdb/env.go
index dfb49c0..50357be 100644
--- a/lmdb/env.go
+++ b/lmdb/env.go
@@ -10,7 +10,6 @@ import "C"
 
 import (
 	"errors"
-	"fmt"
 	"os"
 	"runtime"
 	"unsafe"
@@ -89,7 +88,8 @@ func (env *Env) Open(path string, flags uint, mode os.FileMode) error {
 	return operrno("mdb_env_open", ret)
 }
 
-var errNotOpen = fmt.Errorf("enivornment is not open")
+var errNotOpen = errors.New("enivornment is not open")
+var errNegSize = errors.New("negative size")
 
 // FD returns the open file descriptor (or Windows file handle) for the given
 // environment.  An error is returned if the environment has not been
@@ -326,7 +326,7 @@ func (env *Env) Path() (string, error) {
 // See mdb_env_set_mapsize.
 func (env *Env) SetMapSize(size int64) error {
 	if size < 0 {
-		return fmt.Errorf("negative size")
+		return errNegSize
 	}
 	ret := C.mdb_env_set_mapsize(env._env, C.size_t(size))
 	return operrno("mdb_env_set_mapsize", ret)
@@ -337,7 +337,7 @@ func (env *Env) SetMapSize(size int64) error {
 // See mdb_env_set_maxreaders.
 func (env *Env) SetMaxReaders(size int) error {
 	if size < 0 {
-		return fmt.Errorf("negative size")
+		return errNegSize
 	}
 	ret := C.mdb_env_set_maxreaders(env._env, C.uint(size))
 	return operrno("mdb_env_set_maxreaders", ret)
@@ -367,7 +367,7 @@ func (env *Env) MaxKeySize() int {
 // See mdb_env_set_maxdbs.
 func (env *Env) SetMaxDBs(size int) error {
 	if size < 0 {
-		return fmt.Errorf("negative size")
+		return errNegSize
 	}
 	ret := C.mdb_env_set_maxdbs(env._env, C.MDB_dbi(size))
 	return operrno("mdb_env_set_maxdbs", ret)
diff --git a/lmdb/error.go b/lmdb/error.go
index f9062f4..8f106a6 100644
--- a/lmdb/error.go
+++ b/lmdb/error.go
@@ -6,7 +6,6 @@ package lmdb
 import "C"
 
 import (
-	"fmt"
 	"os"
 	"syscall"
 )
@@ -21,7 +20,7 @@ type OpError struct {
 
 // Error implements the error interface.
 func (err *OpError) Error() string {
-	return fmt.Sprintf("%s: %s", err.Op, err.Errno)
+	return err.Op + ": " + err.Errno.Error()
 }
 
 // The most common error codes do not need to be handled explicity.  Errors can


Test patch:
diff --git a/lmdb/error_test.go b/lmdb/error_test.go
index 72ed1fa..23aee7d 100644
--- a/lmdb/error_test.go
+++ b/lmdb/error_test.go
@@ -1,10 +1,36 @@
 package lmdb
 
 import (
+	"fmt"
 	"syscall"
 	"testing"
 )
 
+func TestErrno_Error(t *testing.T) {
+	operr := &OpError{"testop", fmt.Errorf("testmsg")}
+	msg := operr.Error()
+	if msg != "testop: testmsg" {
+		t.Errorf("message: %q", msg)
+	}
+}
+
+func BenchmarkErrno_Error(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, errno := range []error{
+			syscall.EINVAL,
+			NotFound,
+			MapResized,
+			MapFull,
+		} {
+			operr := &OpError{"mdb_testop", errno}
+			msg := operr.Error()
+			if msg == "" {
+				b.Fatal("empty message")
+			}
+		}
+
+	}
+}
 func TestErrno(t *testing.T) {
 	zeroerr := operrno("testop", 0)
 	if zeroerr != nil {