Go is not as safe as Rust: Types in Go don’t communicate mutability or ownership. I think your best bet here is to be idiomatic in your code and naming conventions. If my function creates a channel and that channel doesn’t get returned out of the function, I think it’s easiest to reason about the code if the function that makes it closes it. It’s like the common pattern:
If you intend on passing ownership of the channel to someFunc, then someFunc's documentation should say that it takes ownership of the channel, just like how bytes.NewBuffer takes ownership of the []byte slice it receives and how io.Reader and io.Writer implementations are not allowed to hold onto the []byte slices passed into them according to their documentation.