Perhaps there are other mechanisms out there too.
I feel like the ability to destroy another thread isnt inherently bad, just... bad with today's languages. Just a feeling though.
The word "channel" doesn't appear a single time in the article, even though goroutines without channels to communicate with each other should never be sharing data. Channels are the synchronization primitive in Go.
Instead of sharing the file descriptor across a goroutine (bro, like WTF), let one go routine manage the file descriptor itself.
Not impossible to deal with but everything you do needs to be designed with cancellation-at-any-point in mind, it doesn't seem worth it to me.