I like generics for collections but that is about it. I've seen "gifted" programmers turn everything into generic classes and functions which then makes it very difficult for anyone else to figure out what is going on.

One reason I like go is it doesn't have all the bells and whistles that give too many choices.

What's wrong with this?

  class Result
  {
    bool IsSuccess {get; set;}
    string Message {get; set;}
    T Data {get; set;}
  }
On many occasions, I like using result types for defining a standard response for calls. It's typed and success / fail can be handled as a cross-cutting concern.

I'm not sure why you'd use a class like this in Go when you have multiple returns and an error interface that already handles this exact use case.

Because multiple return values for handling errors is a strictly inferior and error prone way for dealing with the matter.

    func foo() (*SomeType, error) {
        ...
        return someErr
    }

    ...
    result, err := foo()
    if err != nil {
        // handle err
    }
    // handle result
vs

    type Result struct {
        Err error
        Data SomeType
    }

    func (r *Result) HasError() bool {
        return r.Err != nil
    }

    func bar() *Result {
        ...
        return &Result { ... }
    }

    ...
    result := bar()
    if result.HasError() {
       // handle result.Err
    }
    // handle result

I'm not really sure I see the benefit to the latter. In a language with special operators and built-in types it may be easier (e.g. foo()?.bar()?.commit()), but without these language features I don't see how the Result approach is better.

Go can't really express the Result approach. In Go, it's up to you to remember to check result.HasError(), just like it's up to you to check if err != nil. If you forget that check, you'll try to access the Data and get a nil pointer exception.

The Result approach prevents you from accessing Data if you haven't handled the error, and it does so with a compile-time error.

Even with Go's draconian unused variable rules, I and my colleagues have been burned more than once by forgotten error checks.

there are linters that will help you with that.

https://github.com/kisielk/errcheck

https://golangci-lint.run/usage/linters/ has a solid set of options.