func runfinq() {
	setSystemGoroutine()

	var (
		ef   eface
		ifac iface
	)

	gp := getg()
	gp.isFinalizerGoroutine = true
	for {
		lock(&finlock)
		fb := finq
		finq = nil
		if fb == nil {
			fing = gp
			fingwait = true
			goparkunlock(&finlock, waitReasonFinalizerWait, traceEvGoBlock, 1)
			continue
		}
		unlock(&finlock)
		for fb != nil {
			for i := fb.cnt; i > 0; i-- {
				f := &fb.fin[i-1]

				if f.ft == nil {
					throw("missing type in runfinq")
				}
				fint := f.ft.in[0]
				var param unsafe.Pointer
				switch fint.kind & kindMask {
				case kindPtr:
					// direct use of pointer
					param = unsafe.Pointer(&f.arg)
				case kindInterface:
					ityp := (*interfacetype)(unsafe.Pointer(fint))
					if len(ityp.methods) == 0 {
						// set up with empty interface
						ef._type = &f.ot.typ
						ef.data = f.arg
						param = unsafe.Pointer(&ef)
					} else {
						// convert to interface with methods
						// this conversion is guaranteed to succeed - we checked in SetFinalizer
						ifac.tab = getitab(fint, &f.ot.typ, true)
						ifac.data = f.arg
						param = unsafe.Pointer(&ifac)
					}
				default:
					throw("bad kind in runfinq")
				}
				// This is not a system goroutine while
				// running the actual finalizer.
				// This matters because we want this
				// goroutine to appear in a stack dump
				// if the finalizer crashes.
				// The gc toolchain handles this using
				// a global variable fingRunning,
				// but we don't need that.
				gp.isSystemGoroutine = false
				reflectcall(f.ft, f.fn, false, false, &param, nil)
				gp.isSystemGoroutine = true

				// Drop finalizer queue heap references
				// before hiding them from markroot.
				// This also ensures these will be
				// clear if we reuse the finalizer.
				f.fn = nil
				f.arg = nil
				f.ot = nil
				atomic.Store(&fb.cnt, i-1)
			}
			next := fb.next
			lock(&finlock)
			fb.next = finc
			finc = fb
			unlock(&finlock)
			fb = next
		}
	}
}
// This is the goroutine that runs all of the finalizers
This is the goroutine that runs all of the finalizers
// This is the goroutine that runs all of the finalizers
func runfinq() {
	setSystemGoroutine()
	var (
		ef   eface
		ifac iface
	)
	gp := getg()
	gp.isFinalizerGoroutine = true
	for {
		lock(&finlock)
		fb := finq
		finq = nil
		if fb == nil {
			fing = gp
			fingwait = true
			goparkunlock(&finlock, waitReasonFinalizerWait, traceEvGoBlock, 1)
			continue
		}
		unlock(&finlock)
		for fb != nil {
			for i := fb.cnt; i > 0; i-- {
				f := &fb.fin[i-1]
				if f.ft == nil {
					throw("missing type in runfinq")
				}
				fint := f.ft.in[0]
				var param unsafe.Pointer
				switch fint.kind & kindMask {
				case kindPtr:
					param = unsafe.Pointer(&f.arg)
				case kindInterface:
					ityp := (*interfacetype)(unsafe.Pointer(fint))
					if len(ityp.methods) == 0 {
						ef._type = &f.ot.typ
						ef.data = f.arg
						param = unsafe.Pointer(&ef)
					} else {
						ifac.tab = getitab(fint, &f.ot.typ, true)
						ifac.data = f.arg
						param = unsafe.Pointer(&ifac)
					}
				default:
					throw("bad kind in runfinq")
				}
				gp.isSystemGoroutine = false
				reflectcall(f.ft, f.fn, false, false, &param, nil)
				gp.isSystemGoroutine = true
				f.fn = nil
				f.arg = nil
				f.ot = nil
				atomic.Store(&fb.cnt, i-1)
			}
			next := fb.next
			lock(&finlock)
			fb.next = finc
			finc = fb
			unlock(&finlock)
			fb = next
		}
	}
}
func runfinq ( ) { setSystemGoroutine ( ) var ( ef eface ifac iface ) gp := getg ( ) gp . isFinalizerGoroutine = true for { lock ( & finlock ) fb := finq finq = nil if fb == nil { fing = gp fingwait = true goparkunlock ( & finlock , waitReasonFinalizerWait , traceEvGoBlock , 1 ) continue } unlock ( & finlock ) for fb != nil { for i := fb . cnt ; i > 0 ; i -- { f := & fb . fin [ i - 1 ] if f . ft == nil { throw ( " " ) } fint := f . ft . in [ 0 ] var param unsafe . Pointer switch fint . kind & kindMask { case kindPtr : param = unsafe . Pointer ( & f . arg ) case kindInterface : ityp := ( * interfacetype ) ( unsafe . Pointer ( fint ) ) if len ( ityp . methods ) == 0 { ef . _type = & f . ot . typ ef . data = f . arg param = unsafe . Pointer ( & ef ) } else { ifac . tab = getitab ( fint , & f . ot . typ , true ) ifac . data = f . arg param = unsafe . Pointer ( & ifac ) } default : throw ( " " ) } gp . isSystemGoroutine = false reflectcall ( f . ft , f . fn , false , false , & param , nil ) gp . isSystemGoroutine = true f . fn = nil f . arg = nil f . ot = nil atomic . Store ( & fb . cnt , i - 1 ) } next := fb . next lock ( & finlock ) fb . next = finc finc = fb unlock ( & finlock ) fb = next } } }
This is the goroutine that runs all of the finalizers
This is the goroutine that runs all of the finalizers
// direct use of pointer // set up with empty interface // convert to interface with methods // this conversion is guaranteed to succeed - we checked in SetFinalizer // This is not a system goroutine while // running the actual finalizer. // This matters because we want this // goroutine to appear in a stack dump // if the finalizer crashes. // The gc toolchain handles this using // a global variable fingRunning, // but we don't need that. // Drop finalizer queue heap references // before hiding them from markroot. // This also ensures these will be // clear if we reuse the finalizer.