go - 无效操作 : a > b (operator > not defined on interface)

标签 go interface

是否可以在 Go 中比较两个接口(interface)值?

例如:

func compare(a interface{}, b interface{}) {
    if a > b {
        fmt.Printf("%v is bigger than %v", a, b)
    }
}

但最后,我得到了编译器错误:

invalid operation: a > b (operator > not defined on interface)

Playground :https://play.golang.org/p/iyfw3u6-VeY

最佳答案

您可以比较接口(interface)值的相等性,但不能比较顺序。

Go 规范可能听起来有点困惑,因为相关段落称为 Comparison operators但随后继续区分相等比较和顺序比较(强调我的):

The equality operators == and != apply to operands that are comparable. The ordering operators <, <=, >, and >= apply to operands that are ordered. These terms and the result of the comparisons are defined as follows:

然后:

  • Integer values are comparable and ordered, in the usual way.

  • [...]

  • Interface values are comparable. Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil.

关于接口(interface)的观点没有提到顺序,因此您可以推断接口(interface)值是无序的。因此,您的示例使用运算符 >不编译。

这个,使用相等运算符,而是有效的:

type A struct {
    val int8
}

func main() {
    var x, y int = 1, 2

    compare(x, y) // a and b are not equal

    compare(nil, nil) // a and b are equal

    compare(A{12}, A{12}) // a and b are equal

    compare(A{12}, A{45}) // a and b are not equal
}

func compare(a interface{}, b interface{}) {
    if a == b {
        fmt.Println("a and b are equal")
        return
    }
    fmt.Println("a and b are not equal")
}

作为附加说明,考虑到当接口(interface)值不可等式比较时,编译的代码可能仍然会出现 panic。引用 Go specs again :

A comparison of two interface values with identical dynamic types causes a run-time panic if values of that type are not comparable. This behavior applies not only to direct interface value comparisons but also when comparing arrays of interface values or structs with interface-valued fields.

Slice, map, and function values are not comparable.

这意味着以下代码可以编译但在运行时会出现错误:

compare([]int{12}, []int{12}) // panic: runtime error: comparing uncomparable type []int

警告:上面的段落指定了“相同的动态类型”,因此如果您比较两个不同类型的接口(interface),即使其中一个或两者不可比较,比较将不会 panic 并返回false:

    var a interface{} = 500             // numerical: comparable
    var b interface{} = []string{"foo"} // slice: not comparable
    fmt.Println(a == b)                 // false

参见 Go Playground 中的代码


作为替代方案,使用 Go 1.18 和泛型,您可以显式地将参数类型限制为可排序类型,然后您将能够在函数体中使用排序运算符:

func compare[T constraints.Ordered](a, b T) {
    // works
    if a > b {
        fmt.Printf("%v is bigger than %v", a, b)
    }
}

关于go - 无效操作 : a > b (operator > not defined on interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62944464/

相关文章:

java - Java CRUD 中的接口(interface)隔离

iPhone iOS 如何创建交互式拖动、旋转、调整大小、删除 View 控件?

java - 使用异常处理初始化接口(interface)中的静态字段

typescript - typescript 中的子类化

mongodb - Mongo Go 驱动程序 Count() 方法从 Azure CosmosDB MongoDB Api Count() 获取 "Invalid response from server, value field is not a number"

xml - Golang xml marshal 追加更深的项目?

winapi - 通过 Winspool 打印

base64 - 编码/解码base64

go - 我怎样才能有效地从 Go 中的标准输入读取数字(或者为什么 fmt.Scanf 如此低效)

c# - 如何从 WCF 服务返回 LINQ to SQL 表实体?