> It’s not even enforced error checking, so bad programmers will still be able to write bad code.
Bad programmers will always be able to write bad code. You can't structure a programming language around preventing bad code without completely hamstringing the language.
A false dichotomy. You are correct that you can't outright prevent the writing of bad code in any language without crippling it; nonetheless, the design of a language can be contrived such that writing good code is the path of least resistance. It is not a binary choice between "safe but crippled" and "useful/flexible but unsafe". There is an entire continuum of choices to be made between the two extremes. The design of Go's error handling mechanism, while not the worst approach imaginable, unfortunately makes the programmer exert extra effort in order to do the "right thing".
> the design of a language can be contrived such that writing good code is the path of least resistance.
You can only do this for sufficiently motivated and well-informed programmers.
> The design of Go's error handling mechanism, while not the worst approach imaginable, unfortunately makes the programmer exert extra effort in order to do the "right thing".
Most error handling mechanisms I've seen make doing of of the worst things imaginable (silently throwing away the error) the easiest thing to do. I'm not so sure it's any easier or harder to do the right thing in Go, in the particular context of a highly concurrent system.
EDIT: But I haven't investigated Erlang's mechanism yet. I've heard it's quite good.
> It’s not even enforced error checking, so bad programmers will still be able to write bad code.
Bad programmers will always be able to write bad code. You can't structure a programming language around preventing bad code without completely hamstringing the language.