They were not advised against Go but against cgo. Part of what they want is incremental conversion and cgo is at the same time not-go[0], costly[1] and complex[2], and then you still need to manage the Go runtime (GC & al) from within your C system. That makes integrating the two difficult, especially when you want to replace the existing system piecemeal.
A pure-Go rewrite might be an option (in fact Tor seems pretty firmly in Go's use cases), but that's not what the Tor team is trying to do.
It's still absolutely terrible in terms of ergonomics. You're forced to perform manual memory management, etc. I've done it a few times and I absolutely don't recommend it.
But C code may not keep a Go pointer that persists between calls (because GC). I can imagine that this is a problem for gradually converting code bases.
Sure but that's not what I was replying to? I was only talking about Go->C FFI. If someone didn't know about finalizers, then I've might be trying to insert `free` calls everywhere in their Go code, which could become quite annoying.
Sure but that's not what I was replying to? I was only talking about Go->C FFI.
Sorry, my reply was too brief. I wanted to add that the ergonomics are bad, not just because of freeing memory (for which the inconvenience can indeed be reduced with finalizers and/or Close() methods plus defer). But rules such as this one make Go->C FFI unergonomic as well. To give one example: many linear algebra libraries (e.g. Tensorflow) have their own wrappers around raw arrays to represent tensors (with their dimensionality) [1]. As a consequence of this rule, one cannot just a pointer to the first slice element to such functions (since a pointer to a Go object would be stored in a C struct), but have to malloc an array and copy over data from the slice to the C array.
[1] There are other issues, such aligning slice memory to 16-byte boundaries.
Ah yes, you are absolutely right. I actually modified Rust's regex C API in part because of this problem in Go. I can't remember the details, but they were similar to your example where the only way to work around it was an unavoidable additional allocation.
(Of course, I think the change led to a better overall API. Go just helped me get there in a circuitous way.)
A pure-Go rewrite might be an option (in fact Tor seems pretty firmly in Go's use cases), but that's not what the Tor team is trying to do.
[0] https://dave.cheney.net/2016/01/18/cgo-is-not-go
[1] a cgo->c call is ~100 times more expensive than a go->go call, and ~400 times more expensive than a c->c or rust->c call https://www.reddit.com/r/golang/comments/3oztwi/from_python_...
[2] https://www.cockroachlabs.com/blog/the-cost-and-complexity-o...