demo function in the following example is called, there will be about 1M bytes memory leaking (kind of), until the package-level variable s0 is modified again elsewhere.
var s0 string // a package-level variable
// A demo purpose function.
func f(s1 string) {
s0 = s1[:50]
// Now, s0 shares the same underlying memory block
// with s1. Although s1 is not alive now, but s0
// is still alive, so the memory block they share
// couldn't be collected, though there are only 50
// bytes used in the block and all other bytes in
// the block become unavailable.
}
func demo() {
s := createStringWithLengthOnHeap(1 << 20) // 1M bytes
f(s)
}
[]byte value then convert the []byte value back to string.
func f(s1 string) {
s0 = string([]byte(s1[:50]))
}
func f(s1 string) {
s0 = (" " + s1[:50])[1:]
}
strings.Builder supported since Go 1.10.
import "strings"
func f(s1 string) {
var b strings.Builder
b.Grow(50)
b.WriteString(s1[:50])
s0 = b.String()
}
Repeat function with the count argument as 1 in the strings standard package to clone a string. Since Go 1.12, the underlying implementation of strings.Repeat will make use of strings.Builder, to avoid one unnecessary duplicate.
Clone function has been added to the strings standard package. It becomes the best way to do this job.
g function is called, most memory occupied by the memory block hosting the elements of s1 will be lost (if no more values reference the memory block).
var s0 []int
func g(s1 []int) {
// Assume the length of s1 is much larger than 30.
s0 = s1[len(s1)-30:]
}
s0, so that the aliveness of s0 will not prevent the memory block hosting the elements of s1 from being collected.
func g(s1 []int) {
s0 = make([]int, 30)
copy(s0, s1[len(s1)-30:])
// Now, the memory block hosting the elements
// of s1 can be collected if no other values
// are referencing the memory block.
}
h function is called, the memory block allocated for the first and the last elements of slice s will get lost.
func h() []*int {
s := []*int{new(int), new(int), new(int), new(int)}
// do something with s ...
return s[1:3:3]
}
s from being collected, which in consequence prevents the two memory blocks allocated for the two int values referenced by the first and the last elements of s from being collected.
func h() []*int {
s := []*int{new(int), new(int), new(int), new(int)}
// do something with s ...
// Reset pointer values.
s[0], s[len(s)-1] = nil, nil
return s[1:3:3]
}
time.Ticker Values Which Are Not Used Any More
time.Timer value is not used any more, it will be garbage collected after some time. But this is not true for a time.Ticker value. We should stop a time.Ticker value when it is not used any more.
x and y are not guaranteed to be garbage collected in future garbage collecting.
func memoryLeaking() {
type T struct {
v [1<<20]int
t *T
}
var finalizer = func(t *T) {
fmt.Println("finalizer called")
}
var x, y T
// The SetFinalizer call makes x escape to heap.
runtime.SetFinalizer(&x, finalizer)
// The following line forms a cyclic reference
// group with two members, x and y.
// This causes x and y are not collectable.
x.t, y.t = &y, &x // y also escapes to heap.
}
The Go 101 project is hosted on Github. Welcome to improve Go 101 articles by submitting corrections for all kinds of mistakes, such as typos, grammar errors, wording inaccuracies, description flaws, code bugs and broken links.
If you would like to learn some Go details and facts every serveral days, please follow Go 101's official Twitter account @zigo_101.
reflect standard package.sync standard package.sync/atomic standard package.