Возможно ли инициировать ошибку времени компиляции с пользовательской библиотекой в ​​golang?

Скажем, у меня есть min() (только для примера) вариационная функция для определения наименьшего значения из нескольких предоставленных значений.

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

Как это сделать?

Ответ 1

Вызов функции, которая имеет переменный параметр и передающая аргументы, действительна по спецификации языка. Поэтому вы не можете сделать ошибку времени компиляции.

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

func min(first int, rest ...int) int {
    m := first
    for _, v := range rest {
        if v < m {
            m = v
        }
    }
    return m
}

Это заставит вызывающих абонентов передавать хотя бы один аргумент, иначе это будет ошибка времени компиляции. Эта функция min() может быть вызвана следующим образом:

min(1)
min(1, 2)
min(1, 2, -3)

Но попытка вызвать его без каких-либо аргументов приводит к ошибке времени компиляции:

min() // Error: not enough arguments in call to min

Если вы хотите, чтобы вызывающие абоненты имели не менее 2 аргументов:

func min(first, second int, rest ...int) int {
    return 0 // Implement your logic here
}

Примечание:

Приведенный выше пример также более эффективен, если вызывающий объект просто хочет передать один аргумент, поскольку переменные параметры реализованы с использованием срезов в фоновом режиме, и если вызывающий объект передает только один аргумент, не нужно создавать срез, a nil (это можно проверить, напечатав rest == nil - который будет true).

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

s := []int{1, 2, -3}
fmt.Println(min(s[0], s[1:]...))

который передает первый элемент и разрезает срез, чтобы передать остальное, и используя ..., чтобы передать его как значение для вариационного параметра. Не забудьте проверить, имеет ли срез хотя бы 1 элемент, иначе приведенный выше код будет паниковать во время выполнения.

Попробуйте примеры на Go Playground.

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