As you noted in a comment, now you know why (some) people want generics in Go. :-)
For this particular case, you're probably better off just writing a safeDivideInt
function:
// a/b, but 0 if b == 0
func safeDivideInt(a, b int64) int64 {
if b == 0 {
return 0
}
return a / b
}
and a similar safeDivideUint
function (using uint64
) ... and, if you need it,1 a safeDivideFloat
function, e.g.:
func safeDivideFloat(a, b float64) float64 {
// decide if you want 0/0 handled differently
// decide if you want to check for b being Inf or NaN
// etc.
if b == 0 {
return 0
}
return a / b
}
and then yet again for complex, if you want.
But: there's no easy way to make the Go compiler call one or the other for you. You can write your interface-based function the way you did, and then do type-switching on the various arguments, but it gets quite long as you have to handle all possible combinations. The combinatorial effect is painful no matter how you reduce it. Using reflect
and its type-kind interface does not help here as you still have five int
types, five uint
types (or six if you include uintptr
), the two float
types, and the two complex
types. (It's not clear to me that allowing either of the Uintptr
or UnsafePointer
Kind
s in your divide function makes any sense at all.)
It might, however, make more sense—depending on context—to define your own interface. Here's a working toy example on the Go Playground. I didn't bother putting in Uint and Complex types.
1Note that a runtime 1.0 / 0.0 is +Inf
. The Go specification says:
The result of a floating-point or complex division by zero is not specified beyond the IEEE-754 standard; whether a run-time panic occurs is implementation-specific.
but IEEE-754 calls for Inf and NaN results by default, with exceptions being optional, so I assume this means that the default in Go is no exception raised, meaning "no panic", as well. See, e.g., this Wikipedia entry from which I quote a bit here:
Arithmetic exceptions are (by default) required to be recorded in "sticky" status flag bits. ... By default, an operation always returns a result according to specification without interrupting computation. For instance, 1/0 returns +∞, while also setting the divide-by-zero flag bit (this default of ∞ is designed so as to often return a finite result when used in subsequent operations and so be safely ignored).