一尘不染

是否可以在golang中使用自定义库触发编译时错误?

go

假设,我有一个min()(例如)可变参数函数,可从提供的多个值中定义最小值。

如果调用者未提供任何参数,则我想暂停编译过程(因为这将是调用者中的错误,而不是函数中的错误)。

怎么做?


阅读 244

收藏
2020-07-02

共1个答案

一尘不染

调用具有可变参数且不传递任何参数的函数在语言规范中有效。因此,您不能使其成为编译时错误。

但是,您可以将函数的签名修改为具有一个非可变参数 一个可变参数,然后不带任何参数调用它确实是编译时错误:

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

这将强制调用者传递至少1个参数,否则将是编译时错误。该min()函数可以这样调用:

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

但是尝试不带任何参数调用它会导致编译时错误:

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

如果您希望调用者传递至少两个参数:

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

注意:

如果调用方只想传递1个参数,则上面的示例也更加有效,因为可变参数是在后台使用slice实现的,并且如果调用方仅传递1个参数,则无需创建任何nilslice,将传递一个slice
(这可以通过打印进行验证rest == nil-将是true)。

潜在的不利之处在于,如果您有一个分片,您不仅可以将其传递给函数,还可以执行以下操作:

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

它正在传递第一个元素,并对切片进行切片以传递其余部分,并使用...它作为可变参数的值传递。不要忘记检查分片是否至少包含1个元素,否则上面的代码在运行时会出现问题。

Go Playground上尝试示例。

如果您不能或不想修改函数的签名,则唯一的选择是在运行时崩溃或退出应用程序,但在编译时失败的可能性不大。

2020-07-02