The best solution here is a map, using keys as the set. So something like:
func dedup(arr []T) (ret []T) {
m := make(map[T]bool)
for _, t := range T {
m[t] = true
}
// optimization: make ret the right size
for t := range m {
ret = append(ret, t)
}
}
I haven’t used Go’s new generics, but I’m guessing this would work fine, provided T is a value type (or can be converted to one). If you know you need deduplication at the start, just use a map at the start.
If you don’t have value types, you’re going to have a hard time regardless of language (would probably need some OOP features, which adds a ton of complexity). But you can get pretty far with that pattern. If you add a Hash() int to your type:
func dedup(are []T) (ret []T) {
m := make(map[int]bool)
for _, t := range arr {
h := t.Hash()
if !m[h] {
m[h] = true
ret = append(ret, t)
}
}
}
err… people just did not print any of the relevant information in error cases
That’s what error wrapping is for:
if err != nil {
return fmt.Errorf("context: %w", err)
}
This makes it so you can use the errors package to unwrap errors or check if an error is a given type. Or you can propagate it like I’ve shown above.
So I see this as programmer error. Rust has the same issue since it’s easy to just throw a ? in there and bail early without additional context. The simpler form is easier to catch in Go vs Rust in a code review because it’s more verbose.
It seems you don’t like verbosity, which is fair. I’m fine with verbosity, I don’t like surprises, and Go has enough of those that I generally avoid it.
The best solution here is a map, using keys as the set. So something like:
I haven’t used Go’s new generics, but I’m guessing this would work fine, provided
T
is a value type (or can be converted to one). If you know you need deduplication at the start, just use amap
at the start.If you don’t have value types, you’re going to have a hard time regardless of language (would probably need some OOP features, which adds a ton of complexity). But you can get pretty far with that pattern. If you add a
Hash() int
to your type:That’s what error wrapping is for:
This makes it so you can use the
errors
package to unwrap errors or check if an error is a given type. Or you can propagate it like I’ve shown above.So I see this as programmer error. Rust has the same issue since it’s easy to just throw a
?
in there and bail early without additional context. The simpler form is easier to catch in Go vs Rust in a code review because it’s more verbose.It seems you don’t like verbosity, which is fair. I’m fine with verbosity, I don’t like surprises, and Go has enough of those that I generally avoid it.