Go: оператор ... в аргументах функции

Модератор: Модераторы разделов

Аватара пользователя
Bizdelnick
Модератор
Сообщения: 21546
Статус: nulla salus bello
ОС: Debian GNU/Linux

Go: оператор ... в аргументах функции

Сообщение Bizdelnick »

Доброго всем!
Упёрся в непонятную мне ошибку. Использую пакет rrd. Проблема при вызове функции со следующей сигнатурой:

Код: Выделить всё

func (u *Updater) Update(args ...interface{}) error

Вот как она используется в примере:

Код: Выделить всё

err := u.Update(time.Now(), i, 1.5*float64(i))

То есть первый аргумент - время, последующие - значения переменных, которые надо записать в RRD.
Вот что делаю я:

Код: Выделить всё

u := rrd.NewUpdater(path)
vals := make([]float64, n)
// тут наполнение среза vals
u.Update(time, vals...)

При компиляции получаю too many arguments in call to u.Update, а если использовать gccgo - то error: invalid use of ‘...’ with non-slice. Что означают эти ошибки? Не понимаю даже, как они соотносятся между собой. Что я сделал не так?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 21546
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Go: оператор ... в аргументах функции

Сообщение Bizdelnick »

А вот такой вариант компилируется благополучно:

Код: Выделить всё

u := rrd.NewUpdater(path)
vals := make([]interface{}, n+1)
vals[0] = time.Now()
// тут наполнение среза vals
u.Update(vals...)

Но почему не работал первоначальный вариант - не понимаю. Кто-нибудь может объяснить? А также - какой смысл в том, что сигнатура функции выглядит не так:

Код: Выделить всё

func (u *Updater) Update(t time.Time, args ...interface{}) error
Было бы, на вид, логичнее, но, вероятно, тут тоже есть какое-то ограничение?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Go: оператор ... в аргументах функции

Сообщение NickLion »

Можно так:

Код: Выделить всё

u.Update(append([]interface{}{time}, vals...)...)


Первоначальный вариант не работал, потому что уже была передана переменная time как args..., а потом ещё vals..., которая уже никуда не попадает, вот и ошибка.

Ну, т.е. time преобразовано к []interfaces{}{time} и передано аргументом в функцию. А vals... указывает, что данный параметр не следует считать элементом, а передавать целиком. А уже начали строить "массив" на основаниии списка элементов, поэтому получаем конфликт.
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 21546
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Go: оператор ... в аргументах функции

Сообщение Bizdelnick »

NickLion писал(а):
15.04.2014 19:17
Первоначальный вариант не работал, потому что уже была передана переменная time как args..., а потом ещё vals..., которая уже никуда не попадает, вот и ошибка.

Разве vals... не раскрывается в набор аргументов, а обрабатывается как-то особо? Чем тогда такая конструкция отличается от передачи среза vals без оператора ...?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: Go: оператор ... в аргументах функции

Сообщение NickLion »

Запись

Код: Выделить всё

func x(a... type) {
}
x(a1, a2, a3)

Это просто синтаксический сахар для записи

Код: Выделить всё

func x(a []type) {
}
x([]type{a1, a2, a3})

Если пишем

Код: Выделить всё

func x(a... type) {
}
v := []type{a1, a2, a3}
x(v...)

То это равноценно

Код: Выделить всё

func x(a []type) {
}
v := []type{a1, a2, a3}
x(v)


А

Код: Выделить всё

func x(a... type) {
}
v := []type{a1, a2, a3}
x(v)

равноценно

Код: Выделить всё

func x(a []type) {
}
v := []type{a1, a2, a3}
x([]type{v})


А в записи

Код: Выделить всё

func x(a... type) {
}
v := []type{a1, a2, a3}
x(t, v...)

получаем

Код: Выделить всё

func x(a []type) {
}
v := []type{a1, a2, a3}
x([]type{t}, v)

Что и приводит к ошибке.

Иными словами один синтаксический сахар не подружился с другим. В Perl'е с этим проще, всё в @_ и замечательно :)
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 21546
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: Go: оператор ... в аргументах функции

Сообщение Bizdelnick »

NickLion писал(а):
16.04.2014 12:02
Что и приводит к ошибке.

Спасибо, теперь стало понятно, почему разные сообщения об ошибках. Просто один компилятор начинает с подсчёта аргументов, другой - с выполнения операций с ними.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали: