Введение

Добро пожаловать в подробный обзор нового пакета cmp в Go версии 1.21. В этом посте мы рассмотрим, как эти обновления оптимизируют сравнение значений, делая ваш код более эффективным и интуитивно понятным. Оставайтесь с нами, чтобы узнать об улучшениях, которые Go 1.21 привносит в пакет cmp, и о том, как они могут улучшить ваш опыт программирования.

Первым шагом является импорт пакета cmp.

import (
 "cmp"
)

Мы можем использовать этот пакет для сравнения. Он предоставляет два метода: Сравнить и Меньше.

Сравнивать

Метод «Сравнить» сравнивает 2 значения:

  • если первое значение меньше второго значения, метод вернет -1
  • если оба значения равны, метод вернет 0
  • если первое значение больше второго значения, метод вернет +1
func Compare[T Ordered](x, y T) int
// in this case, the result will be +1
cmp.Compare(3,2)

Меньше

Мы можем использовать этот метод, чтобы проверить, меньше ли первое значение второго значения. В этом случае результат будет истинным; в противном случае оно будет ложным.

(если оба значения равны, результат будет ложным)

func Less[T Ordered](x, y T) bool
// in this case, the result will be true
cmp.Less(1,2)

Ценности Нан

Мы не можем выполнять сравнения между значениями NaN:

NaN < NaN  // false
NaN > NaN  // false
NaN == NaN // false

Однако интересно то, что с помощью этих методов мы можем работать со значениями NaN. В этом случае:

  • NaN всегда меньше любого значения, отличного от NaN.
  • NaN считается равным значению NaN.

Перейти Исходный код

Ниже приведен исходный код для Сравнить.

func Compare[T Ordered](x, y T) int {
 xNaN := isNaN(x)
 yNaN := isNaN(y)
 if xNaN && yNaN {
  return 0
 }
 if xNaN || x < y {
  return -1
 }
 if yNaN || x > y {
  return +1
 }
 return 0
}

Существует частная функция isNaN, которая проверяет, является ли значение NaN.

func isNaN[T Ordered](x T) bool {
 return x != x
}

Когда мы сравниваем, если NaN равен NaN, результат всегда будет false. Аналогично, если мы сравним, что какое-то значение NaN отличается от другого значения NaN, результат будет true.

То же самое относится и к методу Less; они используют эту частную функцию для сравнения.

func Less[T Ordered](x, y T) bool {
 return (isNaN(x) && !isNaN(y)) || x < y
} 

Исходный код: https://cs.opensource.google/go/go/+/refs/tags/go1.21.0:src/cmp/cmp.go

Заказанный тип

В версии Go 1.21 мы можем использовать Ordered Type вместо внешнего пакета constraints для проведения сравнений в Generics (упорядоченные сравнения).

Например, в версиях до 1.21 мы использовали:

import (
 "fmt"
 "golang.org/x/exp/constraints"
)

func main(){
  oldOrderedValues(2, 4)
}

func oldOrderedValues[N constraints.Ordered](v1, v2 N){
 fmt.Println(v1, v2)
 fmt.Println(v1 !=v2)
 fmt.Println(v1 < v2)
 fmt.Println(v1 > v2)
}

Выход:

2 4
true
true
false

однако в go 1.21 мы можем использовать:

import (
 "cmp"
 "fmt"
)

func main(){
  orderedValues(2,4)
}

func orderedValues[N cmp.Ordered](v1, v2 N){
 fmt.Println(v1, v2)
 fmt.Println(v1 !=v2)
 fmt.Println(v1 < v2)
 fmt.Println(v1 > v2)
}

Выход:

2 4
true
true
false

Заключение

Подводя итог: с помощью пакета cmp мы можем выполнять сравнения, и он очень хорошо работает со значениями NaN. Кроме того, мы можем использовать тип Ordered вместо внешнего пакета ограничений для выполнения сравнений в универсальных шаблонах.

ресурс: blog_go_v21_cmp

блог: Би Блогит