176

So in Python and Ruby there is the splat operator (*) for unpacking an array as arguments. In Javascript there is the .apply() function. Is there a way of unpacking an array/slice as function arguments in Go? Any resources for this would be great as well!

Something along the lines of this:

func my_func(a, b int) (int) {
    return a + b
}

func main() {
    arr := []int{2,4}
    sum := my_func(arr)
}
starball
  • 20,030
  • 7
  • 43
  • 238
eatonphil
  • 13,115
  • 27
  • 76
  • 133

4 Answers4

265

You can use a vararg syntax similar to C:

package main
import "fmt"

func my_func( args ...int) int {
   sum := 0
   for _,v := range args {
      sum = sum + v
   }

   return sum;
}

func main() {
    arr := []int{2,4}
    sum := my_func(arr...)
    fmt.Println("Sum is ", sum)
}

Now you can sum as many things as you'd like. Notice the important ... after when you call the my_func function.

Running example: http://ideone.com/8htWfx

Hunter McMillen
  • 59,865
  • 24
  • 119
  • 170
  • 1
    `...` works for `slices`. Do we have something similar for type `array`? – Yogesh May 07 '21 at 16:29
  • 5
    @Yogesh I may be a bit late, but you could always do something like `arr := [3]int{1, 2, 3}; my_func(arr[:]...)`, which turns it into a slice and then unpacks it. – Kyle Anderson Oct 26 '21 at 21:32
  • 8
    how we can handle that when function expect ```...interface{}``` and our slice is another type – Mahdi mehrabi Apr 23 '22 at 18:44
18

Either your function is varargs, in which you can use a slice with the ... notation as Hunter McMillen shows, or your function has a fixed number of arguments and you can unpack them when writing your code.

If you really want to do this dynamically on a function of fixed number of arguments, you can use reflection:

package main
import "fmt"
import "reflect"

func my_func(a, b int) (int) {
    return a + b
}

func main() {
    arr := []int{2,4}
    var args []reflect.Value
    for _, x := range arr {
        args = append(args, reflect.ValueOf(x))
    }
    fun := reflect.ValueOf(my_func)
    result := fun.Call(args)
    sum := result[0].Interface().(int)
    fmt.Println("Sum is ", sum)
}
newacct
  • 119,665
  • 29
  • 163
  • 224
  • I'm curious to see how this benchmarks against the varargs approach. I would assume it would perform less efficiently, but I'll have to look into it. – Hunter McMillen Jul 10 '13 at 03:24
  • @HunterMcMillen did you get any insight about performance comparison? – AkiRoss Sep 14 '15 at 14:45
  • @AkiRoss probably, but it was so long ago that I have forgotten the results :| – Hunter McMillen Sep 14 '15 at 14:59
  • 1
    lol ok, not a big deal: I suppose it's slower anyway, maybe I'll run some tests myself. Thanx – AkiRoss Sep 14 '15 at 18:44
  • sum := result[0].Interface().(int) --> what is this syntax do? – Krishna ps Oct 23 '21 at 19:50
  • @Krishnaps: Look at the documentation of `reflect.Value`'s `Call()` method. It returns a slice of `Value`s, corresponding to multiple return values in Go. `result` is this slice of `Value`s. Assuming we are only dealing with functions that return one value, we just take the first one (`result[0]`), calls the `Interface()` method to obtain the underlying value of the `reflect.Value`, and then asserts it to the return type we expect (in this case `int`). – newacct Oct 24 '21 at 02:45
-4

https://play.golang.org/p/2nN6kjHXIsd

I had a reason to unpack some vars from a map[string]string with single quotes around some of them as well as without. Here's the logic for it and the play link up top has the full working snippet.

func unpack(a map[string]string) string {

var stmt, val string
var x, y []string
for k, v := range a {
    x = append(x, k)
    y = append(y, "'"+v+"'")
}

stmt = "INSERT INTO tdo.rca_trans_status (" + strings.Join(x, ", ")
val = ") VALUES (" + strings.Join(y, ",") + ");"

return stmt + val}

Which presents cleanly for a mssql query as:

INSERT INTO tdo.rca_trans_status (rca_json_body, original_org, md5sum, updated, rca_key) VALUES ('blob','EG','2343453463','2009-11-10 23:00:00','prb-180');
Bill H
  • 1
  • 1
-26

No, there's no direct support for this in the language. Python and Ruby, as well as Javascript you're mentioning; are all dynamic/scripting languages. Go is way closer to, for example, C than to any dynamic language. The 'apply' functionality is handy for dynamic languages, but of little use for static languages like C or Go,

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
zzzz
  • 87,403
  • 16
  • 175
  • 139
  • @user7610 you are wrong. You are reffering to different case than in question. In original question there is no variadic parameter in function declaration. – user2846569 Jul 31 '18 at 13:49
  • Yeah, I was, I guess. What Python/Ruby does can be thought of as syntactic sugar for the reflective call that Go supports... – user7610 Jul 31 '18 at 15:58