// Package final call the finalizer befor an object destruction.
// Clear the memeory, recode logs or something else.
// Example:
// Define an type
// type Obj struct {
// 	// ...
// }
//
// func NewObj() *Obj {
// 	a := &obj{}
// 	final.SetFinalizer(a)
// 	return a
// }
//
// func (o *Obj) Final() {
// 	// do stuffs
// }
package final

import (
	"runtime"
)

// Finalizerable clear a object befor destruction
type Finalizerable interface {
	Finalizer()
}

// SetFinalizer set obj to runtime with Finalizerable,
// if obj implements Finalizerable interface, then call it befor obj
// destruction, or do nothing
func SetFinalizer(obj interface{}) {
	runtime.SetFinalizer(obj, doFinal)
}

// ClearFinalizer clear all finalizer on obj
func ClearFinalizer(obj interface{}) {
	runtime.SetFinalizer(obj, nil)
}

func doFinal(obj interface{}) {
	if f, ok := obj.(Finalizerable); ok {
		f.Finalizer()
	}
}
