]> Cypherpunks repositories - gostls13.git/commitdiff
fmt: add Append, Appendln, Appendf
authorRob Pike <r@golang.org>
Sun, 15 May 2022 00:11:56 +0000 (10:11 +1000)
committerRob Pike <r@golang.org>
Tue, 17 May 2022 18:55:46 +0000 (18:55 +0000)
These are straightforward variants of the existing Sprintf etc.,
but append the resulting bytes to a provided buffer rather than
returning a string.

Internally, there is potentially some allocation because the package
uses a pool of buffers to build its output. We make no attempt to
override that, so the result is first printed into the pool and
then copied to the output. Since it is a managed pool, asymptotically
there should be no extra allocation.

Fixes #47579

RELNOTE=yes

Change-Id: Icef797f9b6f0c84d03e7035d95c06cdb819e2649
Reviewed-on: https://go-review.googlesource.com/c/go/+/406177
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

api/next/47579.txt [new file with mode: 0644]
src/fmt/fmt_test.go
src/fmt/print.go

diff --git a/api/next/47579.txt b/api/next/47579.txt
new file mode 100644 (file)
index 0000000..a5d4d9f
--- /dev/null
@@ -0,0 +1,3 @@
+pkg fmt, func Append([]uint8, ...interface{}) []uint8 #47579
+pkg fmt, func Appendf([]uint8, string, ...interface{}) []uint8 #47579
+pkg fmt, func Appendln([]uint8, ...interface{}) []uint8 #47579
index a4c65b8f5ee72398d38b6a354bb2f36724f7279a..aaeac3875a5e671023a9027c59c796e029a5a607 100644 (file)
@@ -1896,3 +1896,47 @@ func TestParsenum(t *testing.T) {
                }
        }
 }
+
+// Test the various Append printers. The details are well tested above;
+// here we just make sure the byte slice is updated.
+
+const (
+       appendResult = "hello world, 23"
+       hello        = "hello "
+)
+
+func TestAppendf(t *testing.T) {
+       b := make([]byte, 100)
+       b = b[:copy(b, hello)]
+       got := Appendf(b, "world, %d", 23)
+       if string(got) != appendResult {
+               t.Fatalf("Appendf returns %q not %q", got, appendResult)
+       }
+       if &b[0] != &got[0] {
+               t.Fatalf("Appendf allocated a new slice")
+       }
+}
+
+func TestAppend(t *testing.T) {
+       b := make([]byte, 100)
+       b = b[:copy(b, hello)]
+       got := Append(b, "world", ", ", 23)
+       if string(got) != appendResult {
+               t.Fatalf("Append returns %q not %q", got, appendResult)
+       }
+       if &b[0] != &got[0] {
+               t.Fatalf("Append allocated a new slice")
+       }
+}
+
+func TestAppendln(t *testing.T) {
+       b := make([]byte, 100)
+       b = b[:copy(b, hello)]
+       got := Appendln(b, "world,", 23)
+       if string(got) != appendResult+"\n" {
+               t.Fatalf("Appendln returns %q not %q", got, appendResult+"\n")
+       }
+       if &b[0] != &got[0] {
+               t.Fatalf("Appendln allocated a new slice")
+       }
+}
index 33f5541629097c3ae1c77b5c0535702178025892..2af7bd0c426e03e2123bffcb2fb11cae46935075 100644 (file)
@@ -222,6 +222,16 @@ func Sprintf(format string, a ...any) string {
        return s
 }
 
+// Appendf formats according to a format specifier, appends the result to the byte
+// slice, and returns the updated slice.
+func Appendf(b []byte, format string, a ...any) []byte {
+       p := newPrinter()
+       p.doPrintf(format, a)
+       b = append(b, p.buf...)
+       p.free()
+       return b
+}
+
 // These routines do not take a format string
 
 // Fprint formats using the default formats for its operands and writes to w.
@@ -252,6 +262,16 @@ func Sprint(a ...any) string {
        return s
 }
 
+// Append formats using the default formats for its operands, appends the result to
+// the byte slice, and returns the updated slice.
+func Append(b []byte, a ...any) []byte {
+       p := newPrinter()
+       p.doPrint(a)
+       b = append(b, p.buf...)
+       p.free()
+       return b
+}
+
 // These routines end in 'ln', do not take a format string,
 // always add spaces between operands, and add a newline
 // after the last operand.
@@ -284,6 +304,17 @@ func Sprintln(a ...any) string {
        return s
 }
 
+// Appendln formats using the default formats for its operands, appends the result
+// to the byte slice, and returns the updated slice. Spaces are always added
+// between operands and a newline is appended.
+func Appendln(b []byte, a ...any) []byte {
+       p := newPrinter()
+       p.doPrintln(a)
+       b = append(b, p.buf...)
+       p.free()
+       return b
+}
+
 // getField gets the i'th field of the struct value.
 // If the field is itself is an interface, return a value for
 // the thing inside the interface, not the interface itself.