Descompactar Array como Argumentos

103

Portanto, em Python e Ruby existe o operador splat (*) para descompactar um array como argumentos. Em Javascript existe a função .apply (). Existe uma maneira de descompactar uma matriz / fatia como argumentos de função em Go? Quaisquer recursos para isso também seriam ótimos!

Algo mais ou menos assim:

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

func main() {
    arr := []int{2,4}
    sum := my_func(arr)
}

Peço desculpas se estou cometendo erros sintáticos / variados. Sou novo em Go.

Eatonphil
fonte
4
Em primeiro lugar, arrnão é uma matriz. É uma fatia .
newacct

Respostas:

159

Você pode usar uma sintaxe vararg semelhante a 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)
}

Agora você pode somar quantas coisas quiser. Observe o importante ...depois ao chamar a my_funcfunção.

Exemplo de execução: http://ideone.com/8htWfx

Hunter McMillen
fonte
8

Ou sua função é varargs, em que você pode usar uma fatia com a ...notação como mostra Hunter McMillen, ou sua função tem um número fixo de argumentos e você pode descompactá-los ao escrever seu código.

Se você realmente deseja fazer isso dinamicamente em uma função de número fixo de argumentos, pode usar reflexão:

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
fonte
Estou curioso para ver como isso se compara à abordagem dos varargs. Eu presumiria que seu desempenho seria menos eficiente, mas terei que dar uma olhada nisso.
Hunter McMillen
@HunterMcMillen você obteve algum insight sobre a comparação de desempenho?
AkiRoss
@AkiRoss provavelmente, mas foi há tanto tempo que esqueci os resultados: |
Hunter McMillen
lol ok, não é grande coisa: acho que é mais lento de qualquer maneira, talvez eu mesmo faça alguns testes. Thanx
AkiRoss
0

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

Tive um motivo para descompactar alguns vars de uma string de mapa [string] com aspas simples em torno de alguns deles, bem como sem. Aqui está a lógica para isso e o link play no topo tem o trecho de trabalho completo.

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}

Que é apresentado de forma limpa para uma consulta mssql como:

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
fonte
-16

Não, não há suporte direto para isso no idioma. Python e Ruby, bem como Javascript que você está mencionando; são todas linguagens dinâmicas / de script. Go está muito mais próximo, por exemplo, de C do que de qualquer linguagem dinâmica. A funcionalidade 'aplicar' é útil para linguagens dinâmicas, mas de pouco uso para linguagens estáticas como C ou Go,

zzzz
fonte
@ user7610 você está errado. Você está se referindo a um caso diferente do que está em questão. Na questão original, não há parâmetro variável na declaração da função.
user2846569
Sim, eu estava, eu acho. O que Python / Ruby faz pode ser considerado um açúcar sintático para a chamada reflexiva que Go oferece suporte ...
user7610