Слабые указатели
Если вы сильный программист, то не читайте дальше
Слабый указатель (пакет weak в Go 1.24+) ссылается на объект, как обычный указатель. Но в отличие от обычного указателя, слабый указатель не способен удержать объект в памяти. Если на объект ссылаются только слабые указатели, сборщик мусора может освободить занимаемую им память.
Предположим, у нас есть тип blob (реализация скрыта для краткости):
// Blob is a large byte slice.
type Blob []byte
И указатель на блоб размером в 1000 КБ:
b := newBlob(1000)
Мы можем создать слабый указатель (weak.Pointer
) из обычного с помощью weak.Make
. А получить доступ к оригинальному указателю поможет Pointer.Value
:
wb := weak.Make(newBlob(1000))
fmt.Println(wb.Value())
// Blob(1000 KB)
Обычный указатель не позволит сборщику мусора освободить занятую объектом память:
b := newBlob(1000)
fmt.Println("before GC =", b)
runtime.GC()
fmt.Println("after GC =", b)
before GC = Blob(1000 KB)
after GC = Blob(1000 KB)
Слабый указатель же разрешает сборщику мусора освободить память:
wb := weak.Make(newBlob(1000))
fmt.Println("before GC =", wb.Value())
runtime.GC()
fmt.Println("after GC =", wb.Value())
before GC = Blob(1000 KB)
after GC = <nil>
Как видите, Pointer.Value
возвращает nil, если сборщик мусора уже освободил значение по указателю.
Пр этом нет гарантии, что nil вернется сразу после того, как объект перестал использоваться (или в любое другое время позже). Рантайм сам решает, когда освобождать память, и освобождать ли вообще.
Слабые указатели могут пригодиться для реализации кэша больших объектов. Они гарантируют, что объект не будет оставаться в памяти только потому, что он находится в кэше.
Мы еще поговорим об этом в следующий раз.
★ Подписывайтесь на новые заметки.