Rozpakuj tablicę jako argumenty

106

Tak więc w Pythonie i Rubim jest operator splat (*) do rozpakowywania tablicy jako argumentów. W JavaScript jest funkcja .apply (). Czy istnieje sposób rozpakowania tablicy / wycinka jako argumentów funkcji w Go? Wszelkie zasoby do tego również byłyby świetne!

Coś w tym stylu:

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

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

Przepraszam, jeśli popełniam błędy składniowe / różne. Jestem nowy w Go.

eatonphil
źródło
4
Przede wszystkim arrnie jest tablicą. To jest kawałek .
newacct

Odpowiedzi:

164

Możesz użyć składni vararg podobnej do 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)
}

Teraz możesz zsumować tyle rzeczy, ile chcesz. Zwróć uwagę na ważne ...po wywołaniu my_funcfunkcji.

Uruchomiony przykład: http://ideone.com/8htWfx

Hunter McMillen
źródło
9

Albo twoją funkcją jest varargs, w której możesz użyć plastra z ...notacją taką, jak pokazuje Hunter McMillen, albo twoja funkcja ma stałą liczbę argumentów i możesz je rozpakować podczas pisania kodu.

Jeśli naprawdę chcesz to zrobić dynamicznie na funkcji o stałej liczbie argumentów, możesz użyć refleksji:

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
źródło
Jestem ciekawy, jak to porównuje z podejściem varargów. Zakładam, że będzie działał mniej wydajnie, ale będę musiał się temu przyjrzeć.
Hunter McMillen,
@HunterMcMillen Czy uzyskałeś jakieś informacje na temat porównania wydajności?
AkiRoss
@AkiRoss prawdopodobnie, ale to było tak dawno, że zapomniałem wyników: |
Hunter McMillen
lol ok, nic wielkiego: przypuszczam, że i tak jest wolniej, może sam przeprowadzę kilka testów. Thanx
AkiRoss
0

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

Miałem powód, aby rozpakować kilka zmiennych z łańcucha map [string] z pojedynczymi cudzysłowami wokół niektórych z nich, a także bez. Oto logika, a link do odtwarzania u góry zawiera pełny działający fragment.

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}

Który przedstawia czysto dla zapytania mssql jako:

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.
źródło
-17

Nie, nie ma bezpośredniego wsparcia w tym języku. Python i Ruby, a także Javascript, o którym wspominasz; są językami dynamicznymi / skryptowymi. Go jest dużo bliższe na przykład C niż jakiemukolwiek dynamicznemu językowi. Funkcja „zastosuj” jest przydatna w przypadku języków dynamicznych, ale mało przydatna w przypadku języków statycznych, takich jak C lub Go,

zzzz
źródło
@ user7610 mylisz się. Odnosisz się do innego przypadku niż w pytaniu. W pierwotnym pytaniu w deklaracji funkcji nie ma parametru wariadycznego.
user2846569
Tak, chyba tak. To, co robi Python / Ruby, można uznać za cukier składniowy dla odblaskowego wywołania, które obsługuje Go ...
user7610