MustString, MustStdout, etc
oderwat opened this issue · 4 comments
While using script, I think that it would make stuff easier if we get MustString() MustStdout() and similar constructs. In prototyping, my team and I are using a simple must.OK(), must.OKOne() package to keep the code terse. Currently, we end up writing a lot of:
goVersion := must.OkOne(script.Get("https://go.dev/VERSION?m=text").String())Which would be much more elegant as:
goVersion := script.Get("https://go.dev/VERSION?m=text").MustString()The same applies to the other sinks.
Thanks very much for the suggestion, @oderwat! It's appreciated.
I think it's fair to say there are different approaches to panics in Go. The language itself provides panic() and recover(), but makes no value judgements about how or when to use them. That's up to us.
There is a school of thought that likes to use panics in the same sort of way that some other languages use exceptions: as a flow control mechanism, just like break or return. Fans of this style would say that it requires fewer lines of code than returning and checking an error. On the other hand, I think they'd have to admit that it can be harder for a reader to understand how control is going to flow in a program like this, because panics can happen implicitly, without the code actually saying "Hey, I can panic here! Watch out for that!"
Another way of using panics is to treat them as rare, unexpected, and unhandleable problems that usually indicate an internal program bug. For example, if your code is supposed to ensure that such-and-such a variable isn't nil, but you find nevertheless that it is, the only available option might be to panic. Because of this, it usually doesn't make sense to recover such panics, because they signal that the program is in some unexpected, unexplained, and unknown state: trying to continue in such a state makes no sense, and could even be harmful.
I personally lean towards the second way of thinking: I don't tend to use panics as a control flow mechanism, and while my programs might be longer as a result, I think they're also easier to understand. I like to say, because writers enjoy thinking up pithy expressions, that “good programs shouldn't panic, and neither should good programmers”.
In other words, the way I personally would prefer to write the example that you gave would be something like this:
version, err := script.Get("https://go.dev/VERSION?m=text").String()
if err != nil {
log.Fatalf("couldn't fetch current Go version: %v", err)
}
fmt.Println("The current Go version is", version)I'm sure lots of people would find this painfully verbose, but that's okay. I don't need everyone to agree with me about how to write Go. (What a boring world that would be!)
So while I completely see the point of your argument, and it makes sense in the context of the code you're writing, I hope you understand why I'm not that keen to introduce this idea into my version of the script library. Of course, you should feel free to create your own version of it that works exactly the way you want. Not only would I not mind that in the least, I'd be delighted.
And thanks again for opening the issue—others are welcome to weigh in with their own views or suggestions about it.
You lecture me about panics and give an example with log. Fatal ... Come on!
I understand it's upsetting when your suggestion isn't accepted—believe me, I know what that's like! However, it is welcome and it is valued, so, as I say, I'm leaving the issue open to gather feedback from other users.
All the same, your recent interactions haven't lived up to the spirit of our Code of Conduct, so I've put a temporary block on you, just to give a pause for reflection and let emotions cool a little. I want to emphasise that this is temporary, and if and when you decide you're willing to abide by the CoC, you'll be most welcome to return to the project and continue making good contributions.
You are welcome to create this issue by yourself. I do not have an issue with it anymore.