Go Variadic Function
Variadic function āĻšāϞ⧠āĻāĻŽāύ āĻāĻāĻāĻŋ āĻĢāĻžāĻāĻļāύ āϝāĻž āϝā§āĻā§āύ⧠āϏāĻāĻā§āϝāĻ argument āύāĻŋāϤ⧠āĻĒāĻžāϰā§āĨ¤
đ§ē āĻ ā§āϝāĻžāύāĻžāϞāĻāĻŋ: āĻŦāĻžāĻāĻžāϰā§āϰ āĻŦā§āϝāĻžāĻā§āϰ āĻŽāϤ⧠â āĻāĻāĻāĻž, āĻĻā§āĻā§, āĻŦāĻž āĻĻāĻļāĻāĻž āĻāĻŋāύāĻŋāϏāĻ āϧāϰā§āĨ¤ āĻāϞāĻžāĻĻāĻž āĻāϞāĻžāĻĻāĻž āĻŦā§āϝāĻžāĻ āϞāĻžāĻā§ āύāĻžāĨ¤
ā§§. Syntax đ
// â āĻāĻ ... āĻŽāĻžāύ⧠"āϝā§āĻā§āύ⧠āϏāĻāĻā§āϝāĻ"
func sum(nums ...int) int {
total := 0
for _, n := range nums { // āĻā§āϤāϰ⧠nums āĻšāϞ⧠[]int
total += n
}
return total
}
fmt.Println(sum(1, 2, 3)) // 6
fmt.Println(sum(10, 20)) // 30
fmt.Println(sum()) // 0 â argument āύāĻž āĻĻāĻŋāϞā§āĻ āĻāϞā§āϏāĻžāϧāĻžāϰāĻŖ āĻĢāĻžāĻāĻļāύ vs Variadic:
// â āϏāĻžāϧāĻžāϰāĻŖ â āĻĒā§āϰāϤāĻŋāĻāĻŋ āϏāĻāĻā§āϝāĻžāϰ āĻāύā§āϝ āĻāϞāĻžāĻĻāĻž āĻĢāĻžāĻāĻļāύ āϞāĻŋāĻāϤ⧠āĻšāĻŦā§
func sum2(a, b int) int { return a + b }
func sum3(a, b, c int) int { return a + b + c }
// â
Variadic â āĻāĻāĻāĻžāĻ āϝāĻĨā§āώā§āĻ
func sum(nums ...int) int { /* ... */ }⧍. āĻā§āϤāϰ⧠āĻā§āĻāĻžāĻŦā§ āĻāĻžāĻ āĻāϰā§?
...T parameter-āĻāĻŋ āĻĢāĻžāĻāĻļāύā§āϰ āĻā§āϤāϰ⧠[]T slice āĻšāĻŋāϏā§āĻŦā§ āĻāĻžāĻ āĻāϰā§āĨ¤
| āĻĒāϰāĻŋāϏā§āĻĨāĻŋāϤāĻŋ | nums-āĻāϰ āĻā§āϝāĻžāϞ⧠| len(nums) |
|---|---|---|
sum(1, 2, 3) | []int{1, 2, 3} | 3 |
sum(5) | []int{5} | 1 |
sum() | []int{} | 0 |
â ī¸ argument āύāĻž āĻĻāĻŋāϞā§
nilāύāϝāĻŧ, empty slice āĻšāϝāĻŧāĨ¤ āϤāĻŦā§len(nums) == 0āĻĻāĻŋāϝāĻŧā§ āĻā§āĻ āĻāϰāĻžāĻ āύāĻŋāϰāĻžāĻĒāĻĻāĨ¤
ā§Š. Rules đ
| āύāĻŋāϝāĻŧāĻŽ | āĻāĻĻāĻžāĻšāϰāĻŖ |
|---|---|
| āĻāĻāĻāĻŋ āĻĢāĻžāĻāĻļāύ⧠āĻļā§āϧ⧠āĻāĻāĻāĻŋ variadic parameter | func f(a ...int, b ...int) â â compile error |
| āϏāĻŦāϏāĻŽāϝāĻŧ āϏāĻŦāĻžāϰ āĻļā§āώ⧠āĻĨāĻžāĻāϤ⧠āĻšāĻŦā§ | func f(prefix string, vals ...int) â â
|
| Variadic parameter-āĻ āĻāĻāĻ type | ...int, ...string, ...any |
func greet(greeting string, names ...string) {
for _, name := range names {
fmt.Println(greeting, name)
}
}
greet("Hello", "Rahim", "Karim", "Jamal")
// Hello Rahim
// Hello Karim
// Hello Jamalā§Ē. Slice Unpacking â ... āĻ
āĻĒāĻžāϰā§āĻāϰ
āĻāĻā§ āĻĨā§āĻā§ āϤā§āϰāĻŋ slice āĻĒāĻžāϏ āĻāϰāϤ⧠... āĻĻāĻŋāϝāĻŧā§ unpack āĻāϰā§āύ:
nums := []int{1, 2, 3, 4, 5}
sum(nums...) // â
slice unpack āĻāϰ⧠āĻĒāĻžāϏ
sum(nums) // â compile error â []int āĻĒāĻžāϏ āĻāϰāĻž āϝāĻžāĻŦā§ āύāĻž āϏāϰāĻžāϏāϰāĻŋ// Forwarding â āĻāĻ variadic āĻĨā§āĻā§ āĻāϰā§āĻāĻāĻžāϝāĻŧ āĻĒāĻžāϏ āĻāϰāĻž
func logAll(vals ...any) {
fmt.Println(vals...) // â
unpack āĻāϰ⧠fmt.Println-āĻ āĻĒāĻžāϏ
}ā§Ģ. Stdlib-āĻ Variadic (Real-world Usage)
Go standard library-āϤ⧠variadic āĻŦā§āϝāĻžāĻĒāĻāĻāĻžāĻŦā§ āĻŦā§āϝāĻŦāĻšā§āϤ:
| Function | Signature |
|---|---|
fmt.Println | func Println(a ...any) (n int, err error) |
fmt.Sprintf | func Sprintf(format string, a ...any) string |
append | func append(slice []T, elems ...T) []T |
strings.Join | argument āύāϝāĻŧ, āĻāĻŋāύā§āϤ⧠variadic wrapper āϏāĻžāϧāĻžāϰāĻŖ |
// append â Go-āϰ āϏāĻŦāĻā§āϝāĻŧā§ āĻŦā§āĻļāĻŋ āĻŦā§āϝāĻŦāĻšā§āϤ variadic function
s := []int{1, 2}
s = append(s, 3, 4, 5) // â
āĻāĻāĻžāϧāĻŋāĻ element
s = append(s, other...) // â
āĻāϰā§āĻāĻāĻŋ slice unpack āĻāϰā§ā§Ŧ. Functional Options Pattern (Production Critical) đĨ
Production Go code-āĻ variadic function-āĻāϰ āϏāĻŦāĻā§āϝāĻŧā§ āĻā§āϰā§āϤā§āĻŦāĻĒā§āϰā§āĻŖ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻšāϞ⧠Functional Options PatternāĨ¤ āĻāĻāĻŋ grpc, zap, cobra āϏāĻš āĻĒā§āϰāĻžāϝāĻŧ āϏāĻŦ āĻŦāĻĄāĻŧ library-āϤ⧠āĻŦā§āϝāĻŦāĻšā§āϤ āĻšāϝāĻŧāĨ¤
type Server struct {
host string
port int
timeout int
}
type Option func(*Server)
func WithPort(port int) Option {
return func(s *Server) { s.port = port }
}
func WithTimeout(t int) Option {
return func(s *Server) { s.timeout = t }
}
// Variadic āĻĻāĻŋāϝāĻŧā§ optional config āύā§āĻāϝāĻŧāĻž āĻšāĻā§āĻā§
func NewServer(host string, opts ...Option) *Server {
s := &Server{host: host, port: 8080, timeout: 30} // defaults
for _, opt := range opts {
opt(s)
}
return s
}
// Usage â caller āĻļā§āϧ⧠āϝāĻž āĻĻāϰāĻāĻžāϰ āϤāĻžāĻ āĻĻā§āϝāĻŧ
s1 := NewServer("localhost") // āĻļā§āϧ⧠default
s2 := NewServer("localhost", WithPort(9090)) // port override
s3 := NewServer("localhost", WithPort(9090), WithTimeout(60)) // āĻĻā§āĻā§āĻāĻā§āύ āĻāĻāĻž āĻāĻžāϞā§? āύāϤā§āύ option āϝā§āĻ āĻāϰāϞ⧠existing code āĻāĻžāĻā§ āύāĻžāĨ¤
NewServer(host, port, timeout, maxConn, ...)āĻāĻāĻžāĻŦā§ āĻŦāĻžāĻĄāĻŧāϤ⧠āĻĨāĻžāĻāϞ⧠API āĻāĻāĻŋāϞ āĻšāϝāĻŧāĨ¤
ā§. any āĻĻāĻŋāϝāĻŧā§ Mixed Types
// Go 1.18+ â interface{} āĻāϰ āĻĒāϰāĻŋāĻŦāϰā§āϤ⧠'any' āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ
func printAll(vals ...any) {
for _, v := range vals {
switch v := v.(type) {
case int:
fmt.Printf("int: %d\n", v)
case string:
fmt.Printf("string: %s\n", v)
default:
fmt.Printf("unknown: %T\n", v)
}
}
}
printAll(42, "hello", true) // type switch āĻĻāĻŋāϝāĻŧā§ handle āĻāϰāĻž āĻšāĻā§āĻā§ā§Ž. Common Mistakes â ī¸
| āĻā§āϞ | āϏāĻŽāϏā§āϝāĻž | āϏāĻŽāĻžāϧāĻžāύ |
|---|---|---|
sum(nums) â slice āϏāϰāĻžāϏāϰāĻŋ āĻĒāĻžāϏ | compile error | sum(nums...) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ |
| empty args āĻā§āĻ āύāĻž āĻāϰāĻž | index out of range panic | if len(nums) == 0 āĻĻāĻŋāϝāĻŧā§ guard āϰāĻžāĻā§āύ |
any āĻ unchecked type assertion | runtime panic | type switch āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ |
| Variadic parameter āĻĒā§āϰāĻĨāĻŽā§ āϰāĻžāĻāĻž | compile error | āϏāĻŦāϏāĻŽāϝāĻŧ āϏāĻŦāĻžāϰ āĻļā§āώ⧠āϰāĻžāĻā§āύ |
// â Unchecked â panic āĻšāĻŦā§ āϝāĻĻāĻŋ āĻā§āύ⧠arg āύāĻž āĻĨāĻžāĻā§
func first(vals ...int) int {
return vals[0] // panic if len == 0
}
// â
Safe
func first(vals ...int) (int, bool) {
if len(vals) == 0 {
return 0, false
}
return vals[0], true
}⧝. Interview Cheat Sheet
Q: Variadic function-āĻāϰ āĻā§āϤāϰ⧠parameter-āĻāϰ type āĻā§?
...Tparameter āĻĢāĻžāĻāĻļāύā§āϰ āĻā§āϤāϰā§[]Tslice āĻšāĻŋāϏā§āĻŦā§ āĻĨāĻžāĻā§āĨ¤
Q: Argument āύāĻž āĻĻāĻŋāϞ⧠āĻā§ āĻšāϝāĻŧ?
nilāύāϝāĻŧ, empty slice ([]T{}) āĻšāϝāĻŧāĨ¤len == 0āĻšāĻŦā§āĨ¤
Q: Slice āĻā§āĻāĻžāĻŦā§ variadic function-āĻ āĻĒāĻžāϏ āĻāϰāĻŦā§āύ?
func(slice...)â...āĻĻāĻŋāϝāĻŧā§ unpack āĻāϰāϤ⧠āĻšāĻŦā§āĨ¤
Q: āĻāĻāĻāĻŋ āĻĢāĻžāĻāĻļāύ⧠āĻāϤāĻāĻŋ variadic parameter āĻĨāĻžāĻāϤ⧠āĻĒāĻžāϰā§?
āĻŽāĻžāϤā§āϰ āĻāĻāĻāĻŋ, āĻāĻŦāĻ āϏā§āĻāĻŋ āϏāĻŦāϏāĻŽāϝāĻŧ āϏāĻŦāĻžāϰ āĻļā§āώ parameter āĻšāϤ⧠āĻšāĻŦā§āĨ¤
Q: Production-āĻ variadic function-āĻāϰ āϏāĻŦāĻā§āϝāĻŧā§ āĻā§āϰā§āϤā§āĻŦāĻĒā§āϰā§āĻŖ use case āĻā§?
Functional Options Pattern â optional config āĻā§āϰāĻšāĻŖ āĻāϰāĻžāϰ āĻāύā§āϝāĨ¤
grpc.Dial(),zap.New()āĻāĻāĻžāĻŦā§āĻ āĻāĻžāĻ āĻāϰā§āĨ¤
Q: ...any vs āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ type â āĻā§āύāĻāĻž āĻāĻžāϞā§?
āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ type āϏāĻŦāϏāĻŽāϝāĻŧ āĻāĻžāϞ⧠â type safety āĻĨāĻžāĻā§āĨ¤
...anyāĻļā§āϧ⧠āϤāĻāύāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύ āϝāĻāύ āϏāϤā§āϝāĻŋāĻ mixed types āĻĻāϰāĻāĻžāϰ (āϝā§āĻŽāύfmt.Println)āĨ¤