Заранее примечание:
Ваше последнее предложенное решение является самым коротким, понятным и наиболее эффективным способом сравнения трех значений:
if a == b && a == c {
fmt.Println("Clearest: all 3 are equal")
}
или как вариант (на ваш вкус):
if a == b && b == c {
fmt.Println("Clearest: all 3 are equal")
}
Остальная часть этого ответа (что следует) просто играет со спецификацией языка и возможностями языка, представляя то, что я нахожу забавным и креативным. Они не пытаются предоставить превосходное решение.
Попробуйте все приведенные ниже примеры на Go Playground. Примеры основаны на условиях и результатах сравнений, определенных в Спецификация: Операторы сравнения.
Общее примечание: в приведенных ниже примерах я использовал тип 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")
}
По сути, мы помещаем все сопоставимые значения в map
в качестве ключей, и если все равны, на карте будет только 1 пара, поэтому «длина» карты будет равна 1. Тип значения карты не играет. любая роль здесь, это может быть что угодно. Я использовал int
, потому что в результате получается кратчайший составной литерал (который определяет значение map
).
Это решение является гибким, так как вы можете использовать любое количество значений для проверки равенства, а не только 3.
С массивами
Массивы сопоставимы (в отличие от срезов):
if [2]interface{}{a, b} == [2]interface{}{b, c} {
fmt.Println("Arrays: all 3 are equal")
}
Результат сравнения массивов будет true
, если 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")
}
С хитрым map
if map[interface{}]bool{a: b == c}[b] {
fmt.Println("Tricky map: all 3 are equal")
}
Этот составной литерал назначит результат сравнения b == c
ключу a
. И мы запрашиваем значение, связанное с ключом b
. Если a == b
, результатом выражения индексации будет результат b == c
, то есть равны ли все 3 значения. Если a != b
, то результатом будет нулевое значение типа значения, которое равно false
в случае bool
, правильно говоря, что все 3 значения не равны.
С анонимными struct
s
struct
значения также сопоставимы, поэтому:
if struct{ a, b interface{} }{a, b} == struct{ a, b interface{} }{b, c} {
fmt.Println("Anon structs: all 3 are equal")
}
С (по имени) struct
s
Если мы заранее определим простой struct
:
type P struct{ a, b interface{} }
Сравнение будет намного компактнее:
if (P{a, b} == P{b, c}) {
fmt.Println("Structs: all 3 are equal")
}
(Обратите внимание, что выражение оператора if
должно быть заключено в круглые скобки, чтобы избежать неоднозначности разбора - иначе это ошибка времени компиляции!)
С кусочками
Срезы несопоставимы, поэтому нам потребуется помощь от reflect.DeepEqual()
:
if reflect.DeepEqual([]interface{}{a, b}, []interface{}{b, c}) {
fmt.Println("Slices: all 3 are equal")
}
Со вспомогательной функцией
func AllEquals(v ...interface{}) bool {
if len(v) > 1 {
a := v[0]
for _, s := range v {
if a != s {
return false
}
}
}
return true
}
И используя его:
if AllEquals(a, b, c) {
fmt.Println("Helper function: all 3 are equal")
}
Это решение также гибкое, вы можете вызывать AllEquals()
с любым количеством значений.
Обратите внимание, что мы можем сделать функцию AllEquals()
более компактной, если мы также хотим вызвать здесь reflect.DeepEqual()
:
func AllEquals2(v ...interface{}) bool {
if len(v) < 2 {
return true
}
return reflect.DeepEqual(v[:len(v)-1], v[1:])
}
person
icza
schedule
17.06.2016
b == c
. - person JimB   schedule 17.06.2016