In JavaScript, you can use .apply to call a function and pass in an array/slice to use as function arguments.
function SomeFunc(one, two, three) {}
SomeFunc.apply(this, [1,2,3])
I'm wondering if there's an equivalent in Go?
func SomeFunc(one, two, three int) {}
SomeFunc.apply([]int{1, 2, 3})
The Go example is just to give you an idea.
They are called variadic functions and use the ... syntax, see Passing arguments to ... parameters in the language specification.
An example of it:
package main
import "fmt"
func sum(nums ...int) (total int) {
for _, n := range nums { // don't care about the index
total += n
}
return
}
func main() {
many := []int{1,2,3,4,5,6,7}
fmt.Printf("Sum: %v\n", sum(1, 2, 3)) // passing multiple arguments
fmt.Printf("Sum: %v\n", sum(many...)) // arguments wrapped in a slice
}
Playground example
It is possible using reflection, specifically Value.Call, however you really should rethink why you want to do that, also look into interfaces.
fn := reflect.ValueOf(SomeFunc)
fn.Call([]reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20), reflect.ValueOf(30)})
playground
Related
I am looking for an elegant way to unzip a list of arguments in Go. I do not want to use a variadic function for that purpose because in my usecase when writing a function I already know the number of arguments and I want to keep that part simple. However in my usecase the parameters arrive as []interface{}.
I could not find a solution but hey maybe someone out there already knows how to do that?
package main
import (
"fmt"
)
// NON-VARIADIC greater
func greet(n1, n2 string) {
fmt.Printf("%s %s\n", n1, n2)
}
func main() {
l := []interface{}{"hello", "world"}
// works
greet(l[0].(string), l[1].(string))
// does not work: "./args.go:20: not enough arguments in call to greet"
//greet(l...)
// is there something more elegant to unzip the list?
}
You could create a "generic" caller using reflect package, although this comes with overhead and lacks type safety. Unless you have some special case situation and don't know what you want to call in the code, it would be wiser to use the snippet from your question which works, but you consider not elegant.
Example usage of reflect which could be your starting point:
package main
import (
"fmt"
"reflect"
)
func call(f interface{}, args []interface{}) {
// Convert arguments to reflect.Value
vs := make([]reflect.Value, len(args))
for n := range args {
vs[n] = reflect.ValueOf(args[n])
}
// Call it. Note it panics if f is not callable or arguments don't match
reflect.ValueOf(f).Call(vs)
}
func greet(n1, n2 string) {
fmt.Printf("%s %s\n", n1, n2)
}
func main() {
l := []interface{}{"hello", "world"}
call(greet, l)
}
// Output: hello world
https://play.golang.org/p/vbi3CChCdV
I'm not quite sure what you're trying to do. If you want a way to easily pass a slice of two empty interfaces to a function that accepts two strings, you can create a little helper:
func twoStrings(vs []interface{}) (string, string) {
return vs[0].(string), vs[1].(string)
}
Use it as
greet(twoStrings(l))
Playground: http://play.golang.org/p/R8KFwMUT_V.
But honestly, it seems like you're doing something wrong, trying to make the Go type system to do something it cannot do.
A simple example:
package main
import "fmt"
func hereTakeTwo() (x, y int) {
x = 0
y = 1
return
}
func gimmeOnePlease(x int){
fmt.Println(x)
}
func main() {
gimmeOnePlease(hereTakeTwo()) // fix me
}
Is it possible to pass only first returned value from hereTakeTwo() without using an explicit _ assignment? Example of what I would like to avoid:
func main() {
okJustOne, _ := hereTakeTwo()
gimmeOnePlease(okJustOne)
}
What I want is to make gimmeOnePlease function able to receive an undefined number of arguments but take only first one OR a way to call hereTakeTwo function and get only first returned value without the necessity to use _ assignments.
Or on a last resort (crazy idea) use some kind of adapter function, that takes N args and reurns only first one, and have something like:
func main() {
gimmeOnePlease(adapter(hereTakeTwo()))
}
Why? I'm just testing the boundaries of the language and learning how flexible it can be to some purposes.
No, you cannot do that apart from one special case described in the Spec:
As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value.
The best you can do besides the temporary variables (which are the best option) is this:
func first(a interface{}, _ ...interface{}) interface{} {
return a
}
func main() {
gimmeOnePlease(first(hereTakeTwo()).(int))
}
Playground: http://play.golang.org/p/VXv-tsYjXt
Variadic version: http://play.golang.org/p/ulpdp3Hppj
Let's say a function takes a slice of strings:
func Join(strs []string) {
...
}
I have a single string:
a := "y'all ain't got the honey nut?"
How can I convert that string into a slice?
You can create a slice of one item using the following convention:
a := "y'all ain't got the honey nut?"
singleItemArray := []string{a}
strings.Join(singleItemArray);
The actual answer to your question is as simple as []string{"string"}, as miltonb said.
But what I wanted to point out is how easy it is to write and use a variadic function in Go, a function with a variable number of arguments.
You can change signature of your function to F(a ...string). Then, a is slice in the function F, and you can call it like F("a") and F("a", "b"). And when you actually have a slice or array, you can pass it to F by calling F(a...).
Not sure if this syntax fits your job, but I wanted to let you know about it as an option.
The question as phrased actually references Arrays and Slices. The question text is about an array and the code is illustrating using a slice. Therefore there two questions are implied; pass a single item slice, and pass a single item array.
An array: var a [1]string
A slice: var s []string
Passing a single item slice to the function:
func SliceFunc( slc []string) {
fmt.Println(slc)
}
func main() {
a := "stringy"
SliceFunc( []string{a} )
// or an actual array to the same function
b := [...]string { "thingy" }
SliceFunc( []string{b[0] )
}
Passing a single item array to the function.
Here there is an issue, as an array has a fixed length and as a parameter to a function it cannot accept different length arrays so we are left with working function which has limited flexibility:
func ArrayFunc( arr [1]string) {
fmt.Println(slc)
}
func main() {
var a [1]string
a[0] = "stringy"
ArrayFunc( a )
}
It seems that as a generalization sticking to slices is a more flexible solution.
(If you would like more on Slices and Arrays here one blog by Andrew Gerrand covering go slices usage and internals.)
You can utilize append or make:
package main
import "fmt"
func main() {
{
var a []string
a = append(a, "north")
fmt.Println(a)
}
{
a := make([]string, 1)
a[0] = "north"
fmt.Println(a)
}
}
https://golang.org/pkg/builtin
I was going through some code written in Google's Go language, and I came across this:
func Statusln(a ...interface{})
func Statusf(format string, a ...interface{})
I don't understand what the ... means. Does anybody know?
It means that you can call Statusln with a variable number of arguments. For example, calling this function with:
Statusln("hello", "world", 42)
Will assign the parameter a the following value:
a := []interface{}{"hello", "world", 42}
So, you can iterate over this slice a and process all parameters, no matter how many there are. A good and popular use-case for variadic arguments is for example fmt.Printf() which takes a format string and a variable number of arguments which will be formatted according to the format string.
It is variable length argument
func Printf(format string, v ...interface{}) (n int, err error) {
Take for example this signature. Here we define that we have one string to print, but this string can be interpolated with variable number of things (of arbitrary type) to substitude (actually, I took this function from fmt package):
fmt.Printf("just i: %v", i)
fmt.Printf("i: %v and j: %v",i,j)
As you can see here, with variadic arguments, one signature fits all lengths.
Moreover, you can specify some exact type like ...int.
They are variadic functions. These functions accept a variable number of arguments.
Example
The sums function below accepts multiple integers:
package main
import "fmt"
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
func main() {
sum(1, 2)
sum(1, 2, 3)
nums := []int{1, 2, 3, 4}
sum(nums...)
}
For more info
Go By Example: Variadic Functions
Wikipedia: Variadic Functions
Go functions can return multiple values:
func f() (int, int) {
return 2, 3
}
Is there any way to access individual values from such a multi-value returning function except assignment, i.e. suppose there is
func g(i int) {...}
is there is simpler way to write the following two lines?
_, i = f()
g(i)
My personal favorite would be g(f()[1]) but that's not possible either.
The current solution used by the standard library is to write simple helper functions which are dropping the unwanted return values. For example, take a look at the template package.
A lot of functions there return a (*Template, os.Error) tuple, but there is a helper called template.Must() which only returns a *Template and panics if the error isn't nil.
Alternatively, a general helper function like func extract(index int, values ...interface{}) interface{} might do the trick. But since there isn't support for generics yet, I wouldn't write something like that.
Use an anonymous struct instead of multiple return values.
func f() (struct{i,j int}) {
return struct{i, j int}{2, 3}
}
func g(i int) { ... }
func main() {
g(f().j)
}
Of course this only works when you are writing the function. Though you can wrap existing ones with this if you want.
g(func(fst,snd int) int { return snd }(f()))
or defined snd
func snd(x, y int) int {
return y
}
g(snd(f()))
or if function return array
func f() ([2]int) {
return [2]int{2, 3}
}
g(f()[1])
There isn't a simpler way.
A possible solution would look for example like this:
g(f().1)
There is no syntactic support for a feature like this one in Go.