在Go中传递任何类型的惯用方式(同时保持编译时的类型检查?)

I am parsing a form and have written a number of functions func parseAndValidateX(val string) (T, err) where T is any type.

Now I would like to write a closure func catchError(T, Error) T, so that I can do something like:

errors []Error

func catchError(val T, err Error) T {
    if err != nil {
        //append err to errors
    }
    return val
}


data = MyStruct {
Age = catchError(parseAndValidateAge("5")) // Age is a int
DistanceFromHome = catchError(parseAndValidatePi("3.14")) // DistanceFromHome is a float
Location = catchError(parseAndValidatePi("3.14,2.0")) //Location is a custom Struct
}

if len(errors) > 0 {
    // o, oh
}

Is this possible in Go? How can this be done easily/idiomatically?

Nope; you cannot do that since Go has no parametric polymorphism for user-defined functions. All you can do is take and return interface{} and add type assertions at the call sites.

Everything in Go is type-safe if you don't use the unsafe package, so you don't have to worry about that. A type assertion will fail at runtime instead of at compile-time, though.

If you are willing to violate DRY, though:

type errorList []Error

func (l *errorList) addIfNotNil(err Error) {
    if err != nil {
        *l = append(*l, err)
    }
}

func (l *errorList) int(x int, err Error) int {
    l.addIfNotNil(err)
    return x
}

func (l *errorList) float32(x float32, err Error) float32 {
    l.addIfNotNil(err)
    return x
}

list := errorList([]Error{})
data := MyStruct{
    Age: list.int(parseAndValidateAge("5")),
    DistanceFromHome: list.float32(parseAndValidatePi("3.14")),
}