tim*_*ion 7 convention syntax readability equality go
说我有价值观a,b而且c.我想知道他们是否平等.如果我做
if a == b == c{...}
Run Code Online (Sandbox Code Playgroud)
然后我得到一个编译错误
invalid operation: a == b == c (mismatched types bool and TypeOfABandC)
Run Code Online (Sandbox Code Playgroud)
这很明显,因为这解析为:
(a == b) == c
Run Code Online (Sandbox Code Playgroud)
而且(a == b)是一个布尔.
我当然可以这样做:
if a == b && a == c {...}
Run Code Online (Sandbox Code Playgroud)
然而,这看起来并不是很好看并且让人感到困惑.还有另外一种方法吗?
icz*_*cza 21
事先说明:
如果3个值相等,您最后提出的解决方案是最短,最清晰,最有效的比较方法:
if a == b && a == c {
fmt.Println("Clearest: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
或者(根据自己的喜好):
if a == b && b == c {
fmt.Println("Clearest: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
这个答案的其余部分(后面的内容)只是用语言规范和语言的能力来表达,展示我觉得有趣和有创意的东西.他们并不试图提供卓越的解决方案.
在Go Playground上尝试以下所有示例.这些示例建立在Spec:Comparison运算符中定义的比较的术语和结果之上.
一般说明:在下面的示例中,我使用的类型interface{}将适用于您的值具有的任何类型(a,b和c),但如果您知道它们是类型的类型int,那么您也可以使用该特定类型(这将提高效率并缩短例子的长度).
map一套if len(map[interface{}]int{a: 0, b: 0, c: 0}) == 1 {
fmt.Println("Map set: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
实际上,我们将所有可比较的值放入mapas键中,如果全部相等,则地图中只有1对,因此地图的"长度"将为1.地图的值类型不会播放任何角色在这里,它可以是任何东西.我使用,int因为这导致最短的复合文字(定义map值).
此解决方案非常灵活,因为您可以使用任意数量的值来测试所有值是否相等,而不仅仅是3.
阵列具有可比性(与切片不同):
if [2]interface{}{a, b} == [2]interface{}{b, c} {
fmt.Println("Arrays: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
数组比较的结果将是trueif a == b和b == c(如果相应的元素相等).
请注意,您也可以对任意数量的值应用此方法.对于5个值,它看起来像这样:
if [4]interface{}{a, b, c, d} == [4]interface{}{b, c, d, e} {
fmt.Println("Arrays: all 5 are equal")
}
Run Code Online (Sandbox Code Playgroud)
mapif map[interface{}]bool{a: b == c}[b] {
fmt.Println("Tricky map: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
这种复合字面将分配的比较结果b == c的关键a.我们询问与密钥相关的值b.如果a == b,索引表达式的结果将是b == c,即是否所有3个值都相等的结果.如果a != b,则值类型的零值将是结果,false如果bool正确地告知所有3个值不相等.
structsstruct 价值也具有可比性,因此:
if struct{ a, b interface{} }{a, b} == struct{ a, b interface{} }{b, c} {
fmt.Println("Anon structs: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
structs如果我们struct事先定义一个简单的:
type P struct{ a, b interface{} }
Run Code Online (Sandbox Code Playgroud)
比较将更加紧凑:
if (P{a, b} == P{b, c}) {
fmt.Println("Structs: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
(注意if语句的表达式必须放在括号中以避免解析歧义 - 否则它是编译时错误!)
切片不具有可比性,因此我们需要借用以下方面的帮助reflect.DeepEqual():
if reflect.DeepEqual([]interface{}{a, b}, []interface{}{b, c}) {
fmt.Println("Slices: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
func AllEquals(v ...interface{}) bool {
if len(v) > 1 {
a := v[0]
for _, s := range v {
if a != s {
return false
}
}
}
return true
}
Run Code Online (Sandbox Code Playgroud)
并使用它:
if AllEquals(a, b, c) {
fmt.Println("Helper function: all 3 are equal")
}
Run Code Online (Sandbox Code Playgroud)
此解决方案也很灵活,您可以AllEquals()使用任意数量的值进行调用.
请注意,AllEquals()如果我们也愿意在reflect.DeepEqual()这里打电话,我们可以使功能更紧凑:
func AllEquals2(v ...interface{}) bool {
if len(v) < 2 {
return true
}
return reflect.DeepEqual(v[:len(v)-1], v[1:])
}
Run Code Online (Sandbox Code Playgroud)