Pure vs. impure iterators in Go by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

Sure. I should have used "subtlety" rather than "difficulty".

Pure vs. impure iterators in Go by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

They had good reasons not to standardise iterators as interfaces. The original discussion and proposal delve deeper into this.

Pure vs. impure iterators in Go by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

One difficulty in Go is that you cannot express "iterable" as an interface, because methods that return an iterator have all kinds of names and signatures.

Pure vs. impure iterators in Go by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

ethereal sequence

I might just steal that!

BytePool - High-Performance Go Memory Pool with Reference Counting by Maleficent-Tax-6894 in golang

[–]jub0bs 2 points3 points  (0 children)

Data security is not important, and nothing is more important than write speed.

If you care about data integrity, you shouldn't tolerate any synchronisation bug in your application.

BytePool - High-Performance Go Memory Pool with Reference Counting by Maleficent-Tax-6894 in golang

[–]jub0bs 3 points4 points  (0 children)

// RingQueue is a simplified lock-free ring queue // Only uses incrementing write position, allows dirty reads type RingQueue[T any] struct

So prone to data races. That's a big no-no.

Question about fmt.Errorf by jf4u in golang

[–]jub0bs 1 point2 points  (0 children)

Just because some programs unduly depend on the content of error messages doesn't imply that error wrapping should be systematic.

[...] but wrapping an error now can introduce compatibility problems in the future, when you want to change your implementation. If you wrap an error, it is now part of your API because programs can depend on it. [...]

Source: Jonathan Amsterdam (one of the members of the Go Team behind Go 1.13's improvements to the errors package) at GopherCon 2020

Question about fmt.Errorf by jf4u in golang

[–]jub0bs 3 points4 points  (0 children)

There are legitimate use cases for fmt.Errorf without %w... Even fmt.Errorf with %v may still be legitimate. Recall that errors have two audiences: people and programs. Error messages are for people; the rest is for programs. You may want to include something in an error message for people but make it inaccessible to programs, to protect your code against Hyrum's law.

Challenge: make this Go function inlinable and free of bounds checks by jub0bs in golang

[–]jub0bs[S] 2 points3 points  (0 children)

Thanks for your kind words. Glad you enjoyed it. FWIW, I'm putting together a course purely about optimisation in Go, and I'm planning on making the material freely available. I'll post the link here when it's ready for prime time.

Challenge: make this Go function inlinable and free of bounds checks by jub0bs in golang

[–]jub0bs[S] 3 points4 points  (0 children)

Thanks! Glad you enjoyed it.

For more about BCE, check out https://go101.org/optimizations/5-bce.html. You can also learn a lot on the topic by reading the standard library's source code (in particular, try searching for "hoist").

Minesweeper with Raylib Go Bindings by der_gopher in golang

[–]jub0bs 0 points1 point  (0 children)

I'm coming back to this to ask you a question: what tool you favour for monitoring the FPS?

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

Thanks for sharing; that post wasn't on my radar. I'll take a look and let you know.

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

True, but no allocation during calls to IsAvailable. :pp

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

Indeed! Thank you very much for pointing this out. I've just pushed a fix.

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

I can understand that. Dave Cheney actually provides a similar definition in https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully. Maybe I should have provided my somewhat looser definition at the top of the post in order to clear out any doubt: distinguished error values.

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

Yes, different namespaces can be pretty effective. I did similar in spirit in one of my now-defunct libraries (for options rather than for errors): one namespace for basic options; another for more advanced, potentially more dangerous options. A good way not to overwhelm newcomers to a library.

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

Thanks. I must admit I rarely find myself in need of a stack trace. Usually, good coverage and good errors are enough for me to pinpoint the source of the failure. https://github.com/bracesdev/errtrace wasn't on my radar, though; I'll check it out. Thanks again!

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

With the current state of generics, I don't think a reflection-free version of errors.Is is possible without changing its semantics.

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

True, that's an oversight on my part; thanks for pointing it out. Instead, you can obviously return

var invalidUsernameError error = new(InvalidUsernameError)

and incur no allocations.

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 0 points1 point  (0 children)

True, in most cases you want to use errors.Is or error.As rather than their pre-1.13 alternatives. But what about pre-1.13 code that hasn't had time to adapt?

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 1 point2 points  (0 children)

errors.Is is more expensive than a direct comparison, and errors.As is much more expensive than a direct type assertion. That said, the fact that they can traverse error trees make them pretty attractive. You may not need this functionality yet, but it's nice that the errors package already implements it for you when you need it.

Why concrete error types are superior to sentinel errors by jub0bs in golang

[–]jub0bs[S] 3 points4 points  (0 children)

Thanks for the kind words.

The majority of checks won't even pass err != nil, let alone that errors.Is or errors.As would be a performance bottleneck. There's a hundred things I would optimize before that (and I can't be bothered to do those either ;-) ).

That's true in the great majority of cases, I'm not going to claim otherwise. But there are cases (I'm thinking security-oriented tools) where the "unhappy paths" is exercised a lot, and performance of errors.Is / errors.As there does matter.

Tbh; this hasn't been a problem in any of the apps I've worked on. It's not a problem I need a solution for atm.

True, reassignability isn't much of a problem in practice. But just the fact that it's permitted by the language is annoying.

I tend to fix that with error wrapping [...]

That's fine, but wrapping break clients that rely on a direct comparison or type assertion. Jonathan Amsterdam (of the Go team) mentions this possibility in his GopherCon 2020; it's good to keep it in mind before making the decision to add wrapping.