A function parameter has a static type, but you can still accept golang multiple types at call sites in two mainstream ways: any (empty interface) with a type switch, or generics with a type parameter and a constraint (a golang function type in the sense of func types is different—that is a callable signature used as a value type; see functions in Go). Queries like golang function types, go function types, golang type function, go type function, golang func type, golang function parameter multiple types, and golang pass type as argument usually boil down to one of those patterns. This article compares them with small programs; for variables and interfaces background, follow those guides.
Tested with Go 1.24 on Linux.
any / interface{}: one parameter, many concrete types
If every caller passes a different concrete type but you only need to inspect or dispatch, take any (alias for interface{}) and use a type switch or type assertion.
Route []string and map[string]string through one helper
package main
import "fmt"
func A(i []string) { C(i) }
func B(i map[string]string) { C(i) }
func C(i any) {
fmt.Printf("the type was %T\n", i)
}
func main() {
A([]string{"a"})
B(map[string]string{"k": "v"})
}This prints the dynamic type for each call.
string, int, and float64 with a type switch
package main
import "fmt"
func describe(x any) string {
switch x.(type) {
case string:
return "This is a string"
case int:
return "This is an int"
case float64:
return "This is a float64"
default:
return "default value"
}
}
func main() {
fmt.Println(describe(12))
fmt.Println(describe("abc"))
fmt.Println(describe(11.04))
}Running it prints the three describe lines ending with the int, string, and float64 branches.
Generics: one implementation, int | float64 (and beyond)
Generics (since Go 1.18) let you write a single function whose type parameter V is constrained to a union of types. That is the idiomatic fix when the same algorithm applies to each member of the union—here, summing a slice.
Non-generic duplication for comparison:
package main
import "fmt"
func SumInts(m []int) int {
s := 0
for _, v := range m {
s += v
}
return s
}
func SumFloats(m []float64) float64 {
var s float64
for _, v := range m {
s += v
}
return s
}
func main() {
ints := []int{10, 2, 85, 41, 5}
floats := []float64{10.2, 21.5, 5.6, 40.5, 6.5}
fmt.Printf("Non-generic sums: %v and %v\n", SumInts(ints), SumFloats(floats))
}One generic replacement:
package main
import "fmt"
func SumIntsOrFloats[V int | float64](m []V) V {
var s V
for _, v := range m {
s += v
}
return s
}
func main() {
ints := []int{10, 2, 85, 41, 5}
floats := []float64{10.2, 21.5, 5.6, 40.5, 6.5}
fmt.Printf("Generic sums: %v and %v\n",
SumIntsOrFloats(ints),
SumIntsOrFloats(floats))
}That prints Generic sums: 143 and 84.3 when run locally.
The bracket list [V int | float64] introduces type parameter V allowed to be int or float64; the compiler infers V at each call—this is the usual answer when people search golang pass type as argument but really want compile-time polymorphism.
Choosing a pattern
anyplus a type switch — few branches, unrelated shapes, or a true bag of values.- Named
interface{ ... }— all inputs share behavior you can express as methods (see interfaces). - Generics — the same code path for several concrete types with shared structure (
int | float64,constraints.Ordered, or your own interface constraint).
Summary
Golang function parameter multiple types does not mean listing string | int in a single parameter slot the way some languages allow union parameters; instead you model golang multiple types with any and runtime dispatch, with a proper interface, or with generic type parameters. Go function types and golang func type usually refer to function values (func(int) bool), not multiple argument families—keep that vocabulary separate. Golang type function searches often land on generics or reflect, not on ordinary signatures. Pick any when behavior diverges by type; pick generics when the algorithm is identical for each allowed type.
References
Frequently Asked Questions
1. How do I give a golang function parameter multiple types?
any (formerly interface{}) and branch with a type switch, take a real interface type whose methods all arguments satisfy, or use generics with a type parameter constrained to a union like int | float64 or constraints.Integer.2. What is a golang function type in this context?
func(int) bool; unrelated to accepting multiple argument types unless you mean a generic function func F[T, U](t T, u U).3. When should I use generics instead of any?
int and float64 slices); prefer any plus a type switch when shapes differ a lot or you only need a few cases.4. Can I golang pass type as argument like in some languages?
reflect.Type for reflection-heavy APIs.5. Is empty interface still valid if I see `any` in new code?
any is a predefined alias for interface{}; they mean the same thing.
