reduce allocation in funcPatsubst

benchmark                 old ns/op     new ns/op     delta
BenchmarkFuncPatsubst     2030          1102          -45.71%

benchmark                 old allocs     new allocs     delta
BenchmarkFuncPatsubst     9              1              -88.89%

benchmark                 old bytes     new bytes     delta
BenchmarkFuncPatsubst     297           32            -89.23%
diff --git a/strutil_test.go b/strutil_test.go
index 377780d..0cd77ed 100644
--- a/strutil_test.go
+++ b/strutil_test.go
@@ -91,6 +91,14 @@
 }
 
 func TestSubstPattern(t *testing.T) {
+	concatStr := func(pre, subst, post []byte) string {
+		var s []byte
+		s = append(s, pre...)
+		s = append(s, subst...)
+		s = append(s, post...)
+		return string(s)
+	}
+
 	for _, tc := range []struct {
 		pat  string
 		repl string
@@ -151,7 +159,7 @@
 			t.Errorf(`substPattern(%q,%q,%q)=%q, want %q`, tc.pat, tc.repl, tc.in, got, tc.want)
 		}
 
-		got = string(substPatternBytes([]byte(tc.pat), []byte(tc.repl), []byte(tc.in)))
+		got = concatStr(substPatternBytes([]byte(tc.pat), []byte(tc.repl), []byte(tc.in)))
 		if got != tc.want {
 			fmt.Printf("substPatternBytes(%q,%q,%q)=%q, want %q\n", tc.pat, tc.repl, tc.in, got, tc.want)
 			t.Errorf(`substPatternBytes(%q,%q,%q)=%q, want %q`, tc.pat, tc.repl, tc.in, got, tc.want)