Распаковываем массив как аргументы

107

Итак, в Python и Ruby есть оператор splat (*) для распаковки массива в качестве аргументов. В Javascript есть функция .apply (). Есть ли способ распаковки массива / фрагмента в качестве аргументов функции в Go? Любые ресурсы для этого тоже были бы замечательны!

Что-то вроде этого:

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

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

Прошу прощения, если я допускаю синтаксические / различные ошибки. Я новичок в Go.

Eatonphil
источник
4
Прежде всего, arrэто не массив. Это кусок .
newacct

Ответы:

165

Вы можете использовать синтаксис vararg, аналогичный 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)
}

Теперь вы можете суммировать столько вещей, сколько захотите. Обратите внимание на важное ...после, когда вы вызываете my_funcфункцию.

Пример выполнения: http://ideone.com/8htWfx

Хантер Макмиллен
источник
9

Либо ваша функция - varargs, в которой вы можете использовать срез с ...обозначением, как показывает Хантер МакМиллен, либо ваша функция имеет фиксированное количество аргументов, и вы можете распаковать их при написании кода.

Если вы действительно хотите сделать это динамически для функции фиксированного количества аргументов, вы можете использовать отражение:

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
источник
Мне любопытно посмотреть, как эти тесты сравнивают подход varargs. Я бы предположил, что это будет работать менее эффективно, но мне придется разобраться в этом.
Хантер МакМиллен
@HunterMcMillen вы узнали о сравнении производительности?
AkiRoss
@AkiRoss, наверное, но это было так давно, что я забыл о результатах: |
Хантер МакМиллен,
lol ок, ничего страшного: я все равно думаю медленнее, может я сам проведу тесты. Thanx
AkiRoss
0

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

У меня была причина распаковать некоторые вары из строки map [string] с одинарными кавычками вокруг некоторых из них, а также без них. Вот логика для этого, и ссылка на воспроизведение вверху имеет полный рабочий фрагмент.

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}

Что чисто для запроса mssql выглядит как:

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');
Билл Х
источник
-17

Нет, для этого нет прямой поддержки в языке. Python и Ruby, а также упоминаемый вами Javascript; все являются динамическими языками / языками сценариев. Go гораздо ближе, например, к C, чем к любому динамическому языку. Функциональность «применить» удобна для динамических языков, но мало полезна для статических языков, таких как C или Go,

zzzz
источник
@ user7610 вы ошибаетесь. Вы ссылаетесь на другой случай, чем рассматриваемый. В исходном вопросе в объявлении функции нет вариативного параметра.
user2846569
Да, наверное, был. То, что делает Python / Ruby, можно рассматривать как синтаксический сахар для рефлексивного вызова, который поддерживает Go ...
user7610