runtime.AddCleanup

Помните наш блоб?

b := newBlob(1000)
fmt.Printf("b=%v, type=%T\n", b, b)
b=Blob(1000 KB), type=*main.Blob

Что если мы хотим запустить некоторую функцию очистки (cleanup function), когда объект будет собран сборщиком мусора?

Раньше для этого мы бы вызывали runtime.SetFinalizer, который сложно использовать. Теперь есть его улучшенная версия — runtime.AddCleanup:

func main() {
    b := newBlob(1000)
    now := time.Now()
    // Регистрируем функцию, которую рантайм
    // вызовет после сборки памяти объекта b.
    runtime.AddCleanup(b, cleanup, now)

    time.Sleep(10 * time.Millisecond)
    b = nil
    runtime.GC()
    time.Sleep(10 * time.Millisecond)
}

func cleanup(created time.Time) {
    fmt.Printf(
        "object is cleaned up! lifetime = %dms\n",
        time.Since(created)/time.Millisecond,
    )
}
object is cleaned up! lifetime = 10ms

AddCleanup прикрепляет функцию очистки к объекту. Она выполняется после того как объект становится недоступен (на него больше никто не ссылается).

Функция очистки выполняется в отдельной горутине — она последовательно обрабатывает все вызовы очистки в рамках программы. К одному и тому же указателю можно прикрепить несколько функций очистки.

Обратите внимание, что функция очистки не обязательно выполняется сразу после того, как объект стал недоступен; она может выполниться в любое время в будущем.

Более полный пример, который демонстрирует совместную работу слабых указателей и AddCleanupв песочнице.

★ Подписывайтесь на новые заметки.