рдХрдИ рдЧреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдмрд╛рдЗрдЯреНрд╕ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВред рдмрдлрд╝рд░ ред рдЗрд╕рдХрд╛ рдПрдХ рд▓рд╛рдн рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдЖрдкрдХреЛ " рдЫреЛрдЯреЗ рдмрдлрд░ / рдЖрдХрд╛рд░ рдЕрдиреБрдХреВрд▓рди " рдХреЗ рд░реВрдк рдореЗрдВ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдвреЗрд░ рдкрд░ рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдмрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:
type Buffer struct { bootstrap [64]byte
рдХреЗрд╡рд▓ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИред рдпрд╣ рдЕрдиреБрдХреВрд▓рди рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ ред
рдЗрд╕ рд▓реЗрдЦ рдХреЗ рдЕрдВрдд рддрдХ, рдЖрдкрдХреЛ рдкрддрд╛ рдЪрд▓ рдЬрд╛рдПрдЧрд╛ рдХрд┐ рдпрд╣ рдЕрдиреБрдХреВрд▓рди рдХреНрдпреЛрдВ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╣рдо рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЬреИрд╕рд╛ рдХрд┐ рдЗрд░рд╛рджрд╛ рдерд╛, "рдЫреЛрдЯреЗ рдмрдлрд░ рдЕрдиреБрдХреВрд▓рди"
рдЖрдЗрдП bytes.Buffer
рдХреА рдереЛрдбрд╝реА рд╕рд░рд▓ рдкрд░рд┐рднрд╛рд╖рд╛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддреЗ рд╣реИрдВред bytes.Buffer
:
const smallBufSize int = 64 type Buffer struct { bootstrap [smallBufSize]byte buf []byte }
рдЬрдм рд╣рдо Buffer
рдкрд░ рдХреНрд░рд┐рдпрд╛ рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Buffer
рдХреЙрд▓ рдХрд░реЗрдВред рдЗрд╕рдХреЗ Buffer.Write
, рд░рд┐рдХреЙрд░реНрдб рд╣рдореЗрд╢рд╛ buf
рдореЗрдВ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рд░рд┐рдХреЙрд░реНрдб рд╕реЗ рдкрд╣рд▓реЗ, Buffer.grow(n)
рдкреНрд░рддреНрдпреЗрдХ рд╕рдорд╛рди рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ Buffer.grow(n)
, рдЬреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рд╕реНрд▓рд╛рдЗрд╕ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рдЬрдЧрд╣ рд╣реЛред рдЕрдЧрд▓реЗ n
рдмрд╛рдЗрдЯреНрд╕
рд╡рд┐рдХрд╛рд╕ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:
func (b *Buffer) grow(n int) {
рдмрдлрд╝рд░.рдЧреНрд░реЛ рдХреЗ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдорд╛рди
рд╣рдо рдпрд╣ рдзрд╛рд░рдгрд╛ рдмрдирд╛рддреЗ рд╣реИрдВ рдХрд┐ len(b.buf)
рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЗрдЯрд╛ рд▓рдВрдмрд╛рдИ рд╣реИ, рдЬрд┐рд╕реЗ рд╕реНрд▓рд╛рдЗрд╕ рдореЗрдВ рдирдП рдмрд╛рдЗрдЯреНрд╕ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП len(b.buf)
рддрд░реАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Write
рд╣реЛрдЧрд╛ред рдпрд╣ bytes.Buffer
рдореЗрдВ рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИред рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реЗ bytes.Buffer
, рд▓реЗрдХрд┐рди рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдПрдХ рдорд╣рддреНрд╡рд╣реАрди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд┐рд╡рд░рдг рд╣реИред
рдпрджрд┐ b
рд╕реНрдЯреИрдХ рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХреЗ рдЕрдВрджрд░ bootstrap
рдХреЛ рд╕реНрдЯреИрдХ рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╕реНрд▓рд╛рдЗрд╕ b.buf
рдЕрддрд┐рд░рд┐рдХреНрдд рдЖрд╡рдВрдЯрди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд┐рдирд╛ b
рдЕрдВрджрд░ рдореЗрдореЛрд░реА рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░реЗрдЧрд╛ред
рдЬрдм grow
рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ bootstrap
рд╕рд░рдгреА рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рддреЛ рдПрдХ рдирдпрд╛, "рд╡рд╛рд╕реНрддрд╡рд┐рдХ" рд╕реНрд▓рд╛рдЗрд╕ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд╣рд╛рдВ рдкрд┐рдЫрд▓реЗ рд╕реНрдЯреЛрд░реЗрдЬ ("рдЫреЛрдЯреЗ рдмрдлрд░" рд╕реЗ) рддрддреНрд╡реЛрдВ рдХреЛ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЙрд╕рдХреЗ рдмрд╛рдж, Buffer.bootstrap
рдЕрдкрдиреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХрддрд╛ рдЦреЛ рджреЗрдЧрд╛ред рдпрджрд┐ Buffer.Reset
, рддреЛ cap(b.buf)
рд╕рдорд╛рди рд░рд╣реЗрдЧрд╛ рдФрд░ bootstrap
рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреАред
рд╕реНрдореГрддрд┐ рдвреЗрд░ рдореЗрдВ рднрд╛рдЧ рд░рд╣реА рд╣реИ
рдЖрдЧреЗ рдпрд╣ рдЕрдкреЗрдХреНрд╖рд╛ рдХреА рдЬрд╛рддреА рд╣реИ рдХрд┐ рдкрд╛рдардХ рдХрдо рд╕реЗ рдХрдо рд╕рддрд╣реА рд░реВрдк рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реЛ рдЬреЛ рдЧреЛ рдореЗрдВ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╕реЗ рдмрдЪрддрд╛ рд╣реИред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реНрдерд┐рддрд┐ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
func f() *Buffer { var b bytes.Buffer
рдпрд╣рд╛рдВ b
рдХреЛ рдвреЗрд░ рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдХрд╛ рдХрд╛рд░рдг b
рдХреЛ рд▓реАрдХ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рд╕реВрдЪрдХ рд╣реИ:
$ go tool compile -m leak.go leak.go:12:9: &b escapes to heap leak.go:11:6: moved to heap: b
рд╢рдмреНрджрд╛рд╡рд▓реА
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, "рд▓реАрдХ" рдФрд░ "рдкрд▓рд╛рдпрди" рдХрд╛ рдЙрдкрдпреЛрдЧ рд▓рдЧрднрдЧ рдкрд░реНрдпрд╛рдпрд╡рд╛рдЪреА рд░реВрдк рд╕реЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд╕рдВрдХрд▓рдХ рдореЗрдВ рд╣реА рдХреБрдЫ рдЕрдВрддрд░ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореВрд▓реНрдп "рд╣реАрдк рд╕реЗ рдмрдЪ", рд▓реЗрдХрд┐рди рдлрд╝рдВрдХреНрд╢рди рдкреИрд░рд╛рдореАрдЯрд░ "рд▓реАрдХрд┐рдВрдЧ рдкрд░рдо рдПрдХреНрд╕" рд╣реИрдВред
рдПрдХ рд▓реАрдХрд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдкрд╛рд░рд┐рдд рддрд░реНрдХ рдХреЛ рдвреЗрд░ рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рд▓реАрдХрд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░ рддрд░реНрдХреЛрдВ рдХреЛ рдвреЗрд░ рдореЗрдВ рднрд╛рдЧрдиреЗ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред
рдКрдкрд░ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдорд╛рдорд▓рд╛ рдерд╛, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛:
func length() int { var b bytes.Buffer b.WriteString("1") return b.Len() }
рдпрд╣рд╛рдВ рд╣рдореЗрдВ рдХреЗрд╡рд▓ 1 рдмрд╛рдЗрдЯ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рд╕рдм рдХреБрдЫ bootstrap
рдореЗрдВ рдлрд┐рдЯ рдмреИрдарддрд╛ рд╣реИ, рдмрдлрд░ рд╕реНрд╡рдпрдВ рд╕реНрдерд╛рдиреАрдп рд╣реИ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ "рдмрдЪ" рдирд╣реАрдВ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдкрд░рд┐рдгрд╛рдо рд╕рдорд╛рди рд╣реЛрдЧрд╛, рдвреЗрд░ рдкрд░ рдЖрд╡рдВрдЯрди b
ред

рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:
BenchmarkLength-8 20000000 90.1 ns/op 112 B/op 1 allocs/op
рдмреЗрдВрдЪрдорд╛рд░реНрдХ рд▓рд┐рд╕реНрдЯрд┐рдВрдЧ
package p import ( "bytes" "testing" ) func length() int { var b bytes.Buffer b.WriteString("1") return b.Len() } func BenchmarkLength(b *testing.B) { for i := 0; i < bN; i++ { _ = length() } }
рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг 112 рдмреА / рдСрдк
рдЬрдм рд░рдирдЯрд╛рдЗрдо N
рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдЖрд╡рдВрдЯрдирдХрд░реНрддрд╛ рд╕реЗ рдкреВрдЫрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ N
рдмрд╛рдЗрдЯреНрд╕ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдП рдЬрд╛рдПрдВред
рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рд╕рднреА рдкрд░рд┐рдгрд╛рдо GOOS=linux
рдФрд░ GOARCH=AMD64
рдХреЗ рд╕рдВрдпреЛрдЬрди рдХреЗ рд▓рд┐рдП рд╣реИрдВред
package benchmark import "testing"
рдпрджрд┐ рдЖрдк рдЪрд▓рддреЗ go test -bench=. -benchmem
рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рд╛рде go test -bench=. -benchmem
:
BenchmarkAlloc9-8 50000000 33.5 ns/op 16 B/op 1 allocs/op
9 рдмрд╛рдЗрдЯреНрд╕ рдХрд╛ рдЕрдиреБрд░реЛрдз, 16 рдЖрд╡рдВрдЯрд┐рддред рдЕрдм рдмрд╛рдЗрдЯреНрд╕ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВред bytes.Buffer
:
fmt.Println(unsafe.Sizeof(bytes.Buffer{})) => 104
рдЖрдЗрдП $ GOROOT / src / runtime / sizeclasses.go рдХреЛ рджреЗрдЦреЗрдВ :
// class bytes/obj bytes/span objects tail waste max waste // 1 8 8192 1024 0 87.50% // 2 16 8192 512 0 43.75% // 3 32 8192 256 0 46.88% // 4 48 8192 170 32 31.52% // 5 64 8192 128 0 23.44% // 6 80 8192 102 32 19.07% // 7 96 8192 85 32 15.95% // 8 112 8192 73 16 13.56% // ...
рдпрд╣ 96 рдмрд╛рдЗрдЯреНрд╕ рдореЗрдВ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, 112 рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдХреНрдпреЛрдВ рд╣реЛ рд░рд╣рд╛ рд╣реИ?
рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ рдФрд░ рдХреНрдпреЛрдВ
рд╕реНрдерд┐рддрд┐ рдХрд╛ рдХреБрдЫ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╢реБрд░реБрдЖрдд рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдореБрджреНрджреЗ рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкреНрд░рдЬрдирдирдХрд░реНрддрд╛ рднреА рд╣реИред
рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕реНрдерд╛рди рд╕рд┐рд░реНрдл рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ b.buf = b.bootstrap[:]
ред рдпрд╣ рдХреЛрдб рдмрдЪ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд╛ рдЕрдиреБрдорд╛рди b.bootstrap
рдХрд┐ b.bootstrap
"рднрд╛рдЧ рд░рд╣рд╛ рд╣реИ", рдФрд░ рдЪреВрдВрдХрд┐ рдпрд╣ рдПрдХ рд╕рд░рдгреА рд╣реИ, рдпрд╣ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдЕрдВрджрд░ рд╣реА рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╕рднреА b
рдХреЛ рдвреЗрд░ рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдпрджрд┐ рдмреВрдЯрд╕реНрдЯреНрд░реИрдк рдПрдХ рдЯреБрдХрдбрд╝рд╛ рдерд╛, рдПрдХ рд╕рд░рдгреА рдирд╣реАрдВ, рддреЛ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд░ рд╣реА рд╕реНрд▓рд╛рдЗрд╕ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдбрд╣реЙрдХ рдЕрдиреБрдХреВрд▓рди рд╣реИ:
рдЙрддреНрддрд░ рдХреНрдпреЛрдВ рдпрд╣ рдЕрдиреБрдХреВрд▓рди рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдКрдкрд░ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ esc.go # L835-L866 рд╕реЗ рдПрдХ рдирд┐рдЪреЛрдбрд╝ рд╣реИ (рд╕рдВрдкреВрд░реНрдг рдЕрдиреБрдХреВрд▓рди рдХреЛрдб рд╕рдВрджрд░реНрдн рджреНрд╡рд╛рд░рд╛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ):
рдпрд╣рд╛рдВ рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рд╕реВрдЪрдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЗ рд▓рд┐рдП "рд▓реАрдХ" рдХреЗ рдХрдИ рд╕реНрддрд░ рд╣реИрдВ, рдЙрдирдореЗрдВ рд╕реЗ рдореБрдЦреНрдп рд╣реИрдВ:
- рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реА рдмрдЪ рдЬрд╛рддрд╛ рд╣реИ (b es рдПрд╕реНрдХреЗрдк)ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╣реАрдк рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
- рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рддрддреНрд╡ (рдмреА рд╕рд╛рдордЧреНрд░реА рдмрдЪ) рд╕реЗ рдмрдЪ рдЬрд╛рддреЗ рд╣реИрдВред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЛ рднрд╛рдЧрдиреЗ рд╕реЗ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред
рдРрд░реЗ рдХреЗ рд╕рд╛рде рдорд╛рдорд▓рд╛ рдЗрд╕ рд▓рд┐рд╣рд╛рдЬ рд╕реЗ рдЦрд╛рд╕ рд╣реИ рдХрд┐ рдЕрдЧрд░ рдПрд░реЗ рд▓реАрдХ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЙрд╕рдореЗрдВ рдореМрдЬреВрдж рдСрдмреНрдЬреЗрдХреНрдЯ рднреА рд▓реАрдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдЗрд╕ рдмрд╛рдд рдкрд░ рдирд┐рд░реНрдгрдп рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╕реНрдЯреИрдХ рдкрд░ рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЛ рд░рдЦрдирд╛ рд╕рдВрднрд╡ рд╣реИ рдпрд╛ рдирд╣реАрдВ, рдХреЗрд╡рд▓ рдЙрд╕ рдЬрд╛рдирдХрд╛рд░реА рдкрд░ рдирд┐рд░реНрднрд░ рд╣реИ рдЬреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд┐рдП рдЧрдП рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИред Buffer.grow
рд╡рд┐рдзрд┐ рд╕реВрдЪрдХ рджреНрд╡рд╛рд░рд╛ b
рд▓реЗрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдпреБрдХреНрдд рд╕реНрдерд╛рди рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдПрдХ рд╕рд░рдгреА рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рд╣рдо "b escape"
рдХреЛ "b contents escape"
"b escape"
рд╕реЗ рдЕрд▓рдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ "b contents escape"
, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЕрдзрд┐рдХ рдирд┐рд░рд╛рд╢рд╛рд╡рд╛рджреА рд╣реЛрдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЗрд╕ рдирд┐рд╖реНрдХрд░реНрд╖ рдкрд░ рдЖрдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ b
рд╕реНрдЯреИрдХ рдкрд░ рдЬрдЧрд╣ рдХреЗ рд▓рд┐рдП рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реИред
рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд рдорд╛рди рд▓реЗрдВ рдХрд┐ self-assignment
рдкреИрдЯрд░реНрди рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрд╕реА рддрд░рд╣ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ рдЬреИрд╕реЗ рдХрд┐ рдпрд╣ рд╕реНрд▓рд╛рдЗрд╕ рдХреЗ рд▓рд┐рдП рдХрд░рддрд╛ рд╣реИ:
package example var sink interface{} type bad struct { array [10]byte slice []byte } func (b *bad) bug() { b.slice = b.array[:]
рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реНрдЯреИрдХ рдкрд░ b
рд▓рдЧрд╛рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рдЖрдкрджрд╛ рдХреЛ рдЬрдиреНрдо рджреЗрдЧрд╛: рдЬрд┐рд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ b
рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЙрд╕реЗ рдмрд╛рд╣рд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЬрд┐рд╕ рдореЗрдореЛрд░реА рдХреЛ sink
рд╕рдВрджрд░реНрднрд┐рдд рдХрд░реЗрдЧрд╛, рд╡рд╣ рдХрдЪрд░реЗ рд╕реЗ рдЬреНрдпрд╛рджрд╛ рдХреБрдЫ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред
рдПрд░рд┐рдпрд░ рдкреЙрдЗрдВрдЯрд░реНрд╕
рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ Buffer
рдХреЛ рдереЛрдбрд╝рд╛ рдЕрд▓рдЧ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:
const smallBufSize int = 64 type Buffer struct { - bootstrap [smallBufSize]byte + bootstrap *[smallBufSize]byte buf []byte }
рдПрдХ рдирд┐рдпрдорд┐рдд рд╕рд░рдгреА рдХреЗ рд╡рд┐рдкрд░реАрдд, рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реВрдЪрдХ Buffer
рдЕрдВрджрд░ рд╕рднреА рддрддреНрд╡реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдЕрдЧрд░ bootstrap
рдЖрд╡рдВрдЯрди рдвреЗрд░ рдкрд░ рд╣реЛрддрд╛ рд╣реИ рддреЛ рдвреЗрд░ рдкрд░ Buffer
рдЖрд╡рдВрдЯрди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдПрд╕реНрдХреЗрдк рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╕рдВрднрд╡ рд╣реЛрдиреЗ рдкрд░ рд╕реНрдЯреИрдХ рдкрд░ рдкреЙрдЗрдВрдЯрд░ рдлрд╝реАрд▓реНрдб рдЖрд╡рдВрдЯрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдо рдорд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдРрд╕реА Buffer
рдкрд░рд┐рднрд╛рд╖рд╛ рдЕрдзрд┐рдХ рд╕рдлрд▓ рд╣реИред
рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд┐рджреНрдзрд╛рдВрдд рдореЗрдВ рд╣реИред рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рдПрдХ рд╕рд░рдгреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдПрдХ рдирд┐рдпрдорд┐рдд рд╢реНрд░реЗрдгреА рд╕реЗ рдПрдХ рд╕реНрд▓рд╛рдЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рд╣реА рд╢реНрд░реЗрдгреА рдореЗрдВ рдЖрддрд╛ рд╣реИ, рдЬреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╣реА рдирд╣реАрдВ рд╣реИред CL133375: cmd / compile / рдЖрдВрддрд░рд┐рдХ / gc: рдПрд╕реНрд╕реЗрдВрдЧреЛ рдореЗрдВ рдПрд░реЗ рд╕реНрд▓рд╛рдЗрд╕ рд╕реЗрд▓реНрдл-рдЕрд╕рд╛рдЗрди рдХреЛ рд╕рдВрднрд╛рд▓рдирд╛ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рдареАрдХ рдХрд░рдирд╛ рд╣реИред
рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЗрд╕ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рдЧреЛ рд╕рдВрдХрд▓рдХ рдореЗрдВ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд╢реВрдиреНрдп рдорд╛рди рд╣рдордиреЗ рдЦреЛ рджрд┐рдпрд╛
рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, [64]byte
рд╕реЗ *[64]byte
рдореЗрдВ рд╕рдВрдХреНрд░рдордг рдХреА рд╕рдорд╕реНрдпрд╛ рд╣реИ: рдЕрдм рд╣рдо bootstrap
рдЙрдкрдпреЛрдЧ рдмрд┐рдирд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╢реБрд░реВ рдХрд┐рдП рдмрд┐рдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, Buffer
рдХрд╛ рдПрдХ рд╢реВрдиреНрдп рдорд╛рди рдЙрдкрдпреЛрдЧреА рд╣реЛрдирд╛ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реИ, рд╣рдореЗрдВ рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
func NewBuffer() Buffer { return Buffer{bootstrap: new(*[smallBufSize]byte)} }
рд╣рдо Buffer
рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ, рди рдХрд┐ *Buffer
, NewBuffer
рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛рдУрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП (рдпрд╣ рдЧреЛ рдореЗрдВ рдмрд╣реБрдд рд░реВрдврд╝рд┐рд╡рд╛рджреА рд╣реИ), рдФрд░ рдЗрд╕ рддрдереНрдп рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП рдХрд┐ NewBuffer
рд╣рдореЗрд╢рд╛ рдХреЙрд▓ рдХреЗ рд╕реНрдерд╛рди рдкрд░ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреЛрдИ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдирд╣реАрдВ рд╣реЛрдЧреАред
рдПрд╕реНрдХреЗрдк рдХреЙрд▓ рдХреЗ рд╕реНрдерд╛рди рдкрд░ NewBuffer
рдмреЙрдбреА рдХреЛ рдПрдореНрдмреЗрдб рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдпрд╣ рд╕рд╛рдмрд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ new(*[smallBufSize]byte)
рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдлреНрд░реЗрдо рдХреЗ рдЬреАрд╡рдирдХрд╛рд▓ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдЗрд╕реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдРрд╕рд╛ рд╣реИ, рддреЛ рдЖрд╡рдВрдЯрди рд╕реНрдЯреИрдХ рдкрд░ рд╣реЛрдЧрд╛ред
рдЗрдВрдЯреЗрд▓ рдмрд╛рдЗрдЯрдмреБрдл
рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдЕрдиреБрдХреВрд▓рди Intel-go / bytebuf рдкреИрдХреЗрдЬ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдпрд╣ рд▓рд╛рдЗрдмреНрд░реЗрд░реА bytebuf.Buffer
рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд┐рд░реНрдпрд╛рдд рдХрд░рддреА рд╣реИ, рдЬреЛ 99.9% bytes.Buffer
рдбреБрдкреНрд▓рд┐рдХреЗрдЯ bytes.Buffer
ред bytes.Buffer
ред рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ рдПрдХ рдирд┐рд░реНрдорд╛рддрд╛ ( bytebuf.New
) рдФрд░ рдПрдХ рд╕реВрдЪрдХ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рд╕рд░рдгреА рдХреА рд╢реБрд░реВрдЖрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдо рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
type Buffer struct { buf []byte // contents are the bytes buf[off : len(buf)] off int // read at &buf[off], write at &buf[len(buf)] - bootstrap [64]byte // helps small buffers avoid allocation. + bootstrap *[64]byte // helps small buffers avoid allocation. lastRead readOp // last read operation (for Unread*). }
рдпрд╣рд╛рдБ bytes.Buffer
рд╕рд╛рде рдПрдХ рдкреНрд░рджрд░реНрд╢рди рддреБрд▓рдирд╛ рд╣реИред bytes.Buffer
:
name old time/op new time/op delta String/empty-8 138ns ┬▒13% 24ns ┬▒ 0% -82.94% (p=0.000 n=10+8) String/5-8 186ns ┬▒11% 60ns ┬▒ 1% -67.82% (p=0.000 n=10+10) String/64-8 225ns ┬▒10% 108ns ┬▒ 6% -52.26% (p=0.000 n=10+10) String/128-8 474ns ┬▒17% 338ns ┬▒13% -28.57% (p=0.000 n=10+10) String/1024-8 889ns ┬▒ 0% 740ns ┬▒ 1% -16.78% (p=0.000 n=9+10) name old alloc/op new alloc/op delta String/empty-8 112B ┬▒ 0% 0B -100.00% (p=0.000 n=10+10) String/5-8 117B ┬▒ 0% 5B ┬▒ 0% -95.73% (p=0.000 n=10+10) String/64-8 176B ┬▒ 0% 64B ┬▒ 0% -63.64% (p=0.000 n=10+10) String/128-8 368B ┬▒ 0% 256B ┬▒ 0% -30.43% (p=0.000 n=10+10) String/1024-8 2.16kB ┬▒ 0% 2.05kB ┬▒ 0% -5.19% (p=0.000 n=10+10) name old allocs/op new allocs/op delta String/empty-8 1.00 ┬▒ 0% 0.00 -100.00% (p=0.000 n=10+10) String/5-8 2.00 ┬▒ 0% 1.00 ┬▒ 0% -50.00% (p=0.000 n=10+10) String/64-8 2.00 ┬▒ 0% 1.00 ┬▒ 0% -50.00% (p=0.000 n=10+10) String/128-8 3.00 ┬▒ 0% 2.00 ┬▒ 0% -33.33% (p=0.000 n=10+10) String/1024-8 3.00 ┬▒ 0% 2.00 ┬▒ 0% -33.33% (p=0.000 n=10+10)
рдЕрдиреНрдп рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА README рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИред
рд╢реВрдиреНрдп рдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрдерддрд╛ рдФрд░ рдирд┐рд░реНрдорд╛рдг рдХрд╛рд░реНрдп New
рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╛рдзреНрдп рд╣реЛрдиреЗ рдХреЗ рдХрд╛рд░рдг, рдЗрд╕ рдЕрдиреБрдХреВрд▓рди рдХреЛ bytes.Buffer
рд▓рд┐рдП рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред
рдХреНрдпрд╛ рдпрд╣ рддреЗрдЬреА рд╕реЗ bytes.Buffer
рдмрдирд╛рдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рддрд░реАрдХрд╛ рд╣реИред bytes.Buffer
? рдЬрд╡рд╛рдм рд╣реИ рдирд╣реАрдВред рд▓реЗрдХрд┐рди рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдРрд╕реА рд╡рд┐рдзрд┐ рд╣реИ рдЬрд┐рд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдиреНрдпреВрдирддрдо рдмрджрд▓рд╛рд╡ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рдПрд╕реНрдХреЗрдк рдПрдирд╛рд▓рд┐рд╕рд┐рд╕ рдкреНрд▓рд╛рди
рдЕрдкрдиреЗ рд╡рд░реНрддрдорд╛рди рд╕реНрд╡рд░реВрдк рдореЗрдВ, рдЧреЛ рдореЗрдВ рдмрдЪ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдмрд╣реБрдд рдХрдордЬреЛрд░ рд╣реИред рд╕реВрдЪрдХ рдореВрд▓реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рд▓рдЧрднрдЧ рдХреЛрдИ рднреА рдСрдкрд░реЗрд╢рди рдвреЗрд░ рдкрд░ рдЖрд╡рдВрдЯрди рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ, рднрд▓реЗ рд╣реА рдпрд╣ рдПрдХ рдЙрдЪрд┐рдд рдирд┐рд░реНрдгрдп рди рд╣реЛред
рдореИрдВ рдЬреНрдпрд╛рджрд╛рддрд░ рд╕рдордп рдпрд╣ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рдХрд┐ рдореИрдВ рдЗрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреЛрд▓рдВрдЧ / рдЧреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рд╕рдорд░реНрдкрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ , рдЗрд╕рд▓рд┐рдП рдЖрдЧрд╛рдореА рд░рд┐рд▓реАрдЬ (1.12) рдореЗрдВ рдХреБрдЫ рд╕реБрдзрд╛рд░ рд╕рдВрднрд╡ рд╣реИрдВред
рдЖрдк рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЗ рдЗрд╕ рд╣рд┐рд╕реНрд╕реЗ рдХреА рдЖрдВрддрд░рд┐рдХ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдФрд░ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореЗрд░реЗ рдЕрдЧрд▓реЗ рд▓реЗрдЦреЛрдВ рдореЗрдВ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВ рдЕрдиреБрд╢рдВрд╕рд╛рдУрдВ рдХрд╛ рдПрдХ рд╕рдореВрд╣ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рдЬреЛ рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдХреЛрдб рдХреЛ рд╕рдВрд░рдЪрдирд╛ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ рддрд╛рдХрд┐ рдЗрд╕рдореЗрдВ рдХрдо рдЕрд╡рд╛рдВрдЫрд┐рдд рд╕реНрдореГрддрд┐ рдЖрд╡рдВрдЯрди рд╣реЛред