Of course, I understand you don't leak resources if you pay attention and use linters. However, default out-of-scope behavior doesn't exist. In Go, you can defer, and you can also forget to defer. The default behavior is that resource cleanup is a program logic problem that is entirely on the programmer.
The same applies to C#: You program your resource freeing with Dispose (okay, fair so far), and then if the caller forgets to Dispose, you leak. Again, the default behavior is that resource cleanup is a part of the explicitly implemented logic, always.
Compare that to Rust, where you can explicitly drop(), but once a value goes out of scope, its resources are freed.
This is about default and consistent behavior. C# and Go handle memory as a special resource you only sometimes, only in some ways, need to worry about (new, make) but most other resources (files, sockets, threads (if they exist)) become an afterthought and have special logic the programmer needs to worry about *by default*.
The same applies to C#: You program your resource freeing with Dispose (okay, fair so far), and then if the caller forgets to Dispose, you leak. Again, the default behavior is that resource cleanup is a part of the explicitly implemented logic, always.
Compare that to Rust, where you can explicitly drop(), but once a value goes out of scope, its resources are freed.
This is about default and consistent behavior. C# and Go handle memory as a special resource you only sometimes, only in some ways, need to worry about (new, make) but most other resources (files, sockets, threads (if they exist)) become an afterthought and have special logic the programmer needs to worry about *by default*.