5

In every documentation, I read something like that for sentinel errors:

Sentinel errors are usually used to indicate that you cannot start or proceed.

That could also be the case for any possible error, isn't it? Because anything unexpected can happen in Runtime. Does it mean errors that I expect in Runtime but can or should handle better, do I call sentinel errors?

Then I read how they should be used:

Sentinel errors are among the few variables declared at the package level. Their names start with Err (Exception io.EOF). They should be threatened as read-only. (Go compiler cannot enforce this).

Before you define a sentinel error, make sure you need one. Once defined, it becomes part of your public API, and you have committed to making it available in all future backwards-compatible releases.

Or does the way I handle them make them sentinel errors? Could you give me an example to understand clearly, what the difference is?

Would it be wrong to say: Errors, I want to stand sentinel over in Runtime, and I explicitly define in my package root as variables (or constants) are sentinel errors?

I've prepared an example; maybe we can use it as a basis: https://go.dev/play/p/qwi4ligYZYh

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • 1
    *"Would it be wrong to say: ..."* -- It would. You're unnecessarily overthinking it. And trying to make sentinels somehow special when it comes to "public API" and "backwards compatibility" is ridiculous. Anything and everything that you export and make publicly available, you have to support and you have to keep supporting in the future, if you made some kind of backwards-compatibility promise to your users. That kind of commitment-to-keep-your-promise should apply to every exported object in your API, not just sentinels only. – mkopriva Aug 21 '22 at 14:35
  • 1
    [Sentinel values](https://en.wikipedia.org/wiki/Sentinel_value), whether errors or not, are basically special, pre-defined values which you *expect* may be the result of specific processes in specific contexts. They are used to check the results of those processes to find out whether or not the expected state has now come to pass. In short, they are indicators of an expected state. With "sentinel" errors in Go it's the same. They are values that are used to indicate a specific state, and in cases where that specific state is expected, they may not even be considered actual errors. – mkopriva Aug 21 '22 at 14:36
  • 2
    The `io.EOF` error value is a perfect example, say you have a file-reading process and you expect that process to eventually reach the end of the file, so you have that process check for `io.EOF` but, once encountered, you do not consider it an error, instead you simply terminate that process. Or, say, the process encounters `io.EOF` right at the beginning, without being able to read a single byte, then you may opt to return the `io.EOF` error to the caller to indicate that empty files are not valid arguments. – mkopriva Aug 21 '22 at 14:37
  • Dear @mkopriva, many thanks for your efforts; I would like to re-check the content at the next opportunity before I upvote. I have known the term sentinel in other contexts, like https://en.wikipedia.org/wiki/Sentinel_value or https://en.wikipedia.org/wiki/Sentinel_node. It was not immediately apparent to me why someone spoke of sentinel errors. In the end, I also understood that this was nothing special. I think many beginners with different prior knowledge will repeat my mistake. So I don't think it's the world's end if the question stays open. –  Aug 21 '22 at 15:06
  • 1
    I read the Dave's explanation, there are even sentinel errors that signify that an error did not occur, like `go/build.NoGoError`, and `path/filepath.SkipDir` from `path/filepath.Walk`. These are the things that a beginner cannot know. So I would like a little more patience from you. After all, I want to learn and I also pass on my knowledge, as soon as I can do something, I help the people who can't. A little more patience, a little more kindness wouldn't hurt anyone. –  Aug 21 '22 at 15:16
  • I have read Mr Cheney's views on this many times. I really don't understand why it's "bad" to have a "sentinel error." I mean, really? Who is to say that? Lol. His blog post is a bit of riddle. There are millions of lines of code which use errors like this and they work fine and very reliably. – EdH May 01 '23 at 03:11
  • I think the real problem is they implemented error as an interface (and a builtin, so weird) and interfaces can't be constants. And so they defend that somehow. Sure. The golang team also talked about how bad generics were and now generics are implemented. So we will see a fix in go 2.0 :) – EdH May 01 '23 at 03:20

1 Answers1

0

The idea of a sentinel error is semantic more than computer science. The Digital Ocean tutorial on Error handling in go gives a very good explanation of what sentinel errors are (and is where I learned).

Sentinel errors are user defined errors that indicated very specific events that you, as a developer, anticipate & identify as adequately important to define and specify. As such, you declare them at the package level and, in doing so, imply that your package functions may return these errors (thereby committing you in the future to maintain these errors as others depending on your package will be checking for them).

Ex:

var VeryImportantError = fmt.ErrorF("Something very specific happened!")
[...]
if err == VeryImportantError {
    // handle very specific error in very specific way
}

In general these are errors are "usually used to indicate that you cannot start or proceed."

In short, sentinel errors are not special from a compiler perspective. Rather, they are a way of conceptualizing certain, specific, errors that the developer wants to handle in specific ways because they signal specific things.

Ravi Dev
  • 1
  • 1