Use Buffer pool to allocate bytes.Buffer for formatter

Entry.Reader() seams not necessary, removed
diff --git a/entry.go b/entry.go
index 54bfc57..4edbe7a 100644
--- a/entry.go
+++ b/entry.go
@@ -3,11 +3,21 @@
 import (
 	"bytes"
 	"fmt"
-	"io"
 	"os"
+	"sync"
 	"time"
 )
 
+var bufferPool *sync.Pool
+
+func init() {
+	bufferPool = &sync.Pool{
+		New: func() interface{} {
+			return new(bytes.Buffer)
+		},
+	}
+}
+
 // Defines the key when adding errors using WithError.
 var ErrorKey = "error"
 
@@ -29,6 +39,9 @@
 
 	// Message passed to Debug, Info, Warn, Error, Fatal or Panic
 	Message string
+
+	// When formatter is called in entry.log(), an Buffer may be set to entry
+	Buffer *bytes.Buffer
 }
 
 func NewEntry(logger *Logger) *Entry {
@@ -39,21 +52,15 @@
 	}
 }
 
-// Returns a reader for the entry, which is a proxy to the formatter.
-func (entry *Entry) Reader() (*bytes.Buffer, error) {
-	serialized, err := entry.Logger.Formatter.Format(entry)
-	return bytes.NewBuffer(serialized), err
-}
-
 // Returns the string representation from the reader and ultimately the
 // formatter.
 func (entry *Entry) String() (string, error) {
-	reader, err := entry.Reader()
+	serialized, err := entry.Logger.Formatter.Format(entry)
 	if err != nil {
 		return "", err
 	}
-
-	return reader.String(), err
+	str := string(serialized)
+	return str, nil
 }
 
 // Add an error as single field (using the key defined in ErrorKey) to the Entry.
@@ -81,6 +88,7 @@
 // This function is not declared with a pointer value because otherwise
 // race conditions will occur when using multiple goroutines
 func (entry Entry) log(level Level, msg string) {
+	var buffer *bytes.Buffer
 	entry.Time = time.Now()
 	entry.Level = level
 	entry.Message = msg
@@ -90,20 +98,23 @@
 		fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
 		entry.Logger.mu.Unlock()
 	}
-
-	reader, err := entry.Reader()
+	buffer = bufferPool.Get().(*bytes.Buffer)
+	buffer.Reset()
+	defer bufferPool.Put(buffer)
+	entry.Buffer = buffer
+	serialized, err := entry.Logger.Formatter.Format(&entry)
+	entry.Buffer = nil
 	if err != nil {
 		entry.Logger.mu.Lock()
 		fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
 		entry.Logger.mu.Unlock()
-	}
-
-	entry.Logger.mu.Lock()
-	defer entry.Logger.mu.Unlock()
-
-	_, err = io.Copy(entry.Logger.Out, reader)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
+	} else {
+		entry.Logger.mu.Lock()
+		_, err = entry.Logger.Out.Write(serialized)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
+		}
+		entry.Logger.mu.Unlock()
 	}
 
 	// To avoid Entry#log() returning a value that only would make sense for
diff --git a/text_formatter.go b/text_formatter.go
index 6afd0e0..cce61f2 100644
--- a/text_formatter.go
+++ b/text_formatter.go
@@ -57,6 +57,7 @@
 }
 
 func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
+	var b *bytes.Buffer
 	var keys []string = make([]string, 0, len(entry.Data))
 	for k := range entry.Data {
 		keys = append(keys, k)
@@ -65,8 +66,11 @@
 	if !f.DisableSorting {
 		sort.Strings(keys)
 	}
-
-	b := &bytes.Buffer{}
+	if entry.Buffer != nil {
+		b = entry.Buffer
+	} else {
+		b = &bytes.Buffer{}
+	}
 
 	prefixFieldClashes(entry.Data)