The previous implementation incorrectly extracted the type pointer (first word)
from Go interfaces instead of the data pointer (second word). Since all
*net.TCPConn share the same type pointer, this caused:
1. All connections to be identified by the same pointer value
2. Only the first connection to be properly registered in the watcher
3. Finalizers not being set correctly for subsequent connections
4. GC-based cleanup to fail (only 1 connection cleaned up instead of all)
Root cause:
Go interfaces are laid out as [type_ptr, data_ptr] (two machine words).
The old code: `ptr := *(*uintptr)(unsafe.Pointer(&conn))`
only retrieved the type pointer, which is identical for all *net.TCPConn.
Fix:
Changed to extract the second word (data pointer) which uniquely identifies
each connection instance:
iface := ([2]uintptr)(unsafe.Pointer(&conn))
ptr := iface[1] // data pointer
Affected functions:
- aioCreate(): connection registration and finalizer setup
- handleGC(): garbage collection callback handling
Also includes:
- Modernize codebase for Go 1.21+ (interface{} → any, clear() builtin)
- Use sync.Pool inline initialization
- Improve mutex handling with defer patterns
- Enhanced TestGC with 200 connections (requires ≥100 successful GC)
All tests pass with race detector enabled.