1、介绍
众所周知,我们在使用golang的时候没有max和min函数,很多小伙伴在拿go写算法的时候都要去自己简单的构造max和min函数,不过go终于在1.21.0内置 max
和 min
和clear
函数。
2、max 和 min
源码位于/go/src/builtin/builtin.go
// The max built-in function returns the largest value of a fixed number of
// arguments of [cmp.Ordered] types. There must be at least one argument.
// If T is a floating-point type and any of the arguments are NaNs,
// max will return NaN.
func max[T cmp.Ordered](x T, y ...T) T
// The min built-in function returns the smallest value of a fixed number of
// arguments of [cmp.Ordered] types. There must be at least one argument.
// If T is a floating-point type and any of the arguments are NaNs,
// min will return NaN.
func min[T cmp.Ordered](x T, y ...T) T
当go的1.9版本之后加入了泛型,函数内部传入的也是泛型函数,函数入参是cmp.Ordered
,cmp这个包也是go1.21.0新增的package,它提供了三个函数,分别是less
、compare
、isNaN
共我们使用。
首先我们看一下Ordered
结构体到底是什么
// Ordered is a constraint that permits any ordered type: any type
// that supports the operators < <= >= >.
// If future releases of Go add new ordered types,
// this constraint will be modified to include them.
//
// Note that floating-point types may contain NaN ("not-a-number") values.
// An operator such as == or < will always report false when
// comparing a NaN value with any other value, NaN or not.
// See the [Compare] function for a consistent way to compare NaN values.
type Ordered interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~string
}
可以看出,在函数入参可以传入上述类型做比较,是可比较类型参数,例如整型、浮点型、字符串等。如遇到不可比较类型返回的就是NaN
结果。
不可比较类型就是不能参与运算符的比较,比如slice
,map
,function
等,它们不可以作为max
和min
的参数传递。但是这些类型可以与nil
做比较的。
例1
func main() {
m := min()
fmt.Println(m) // invalid operation: not enough arguments for min() (expected 1, found 0)
}
没有传参,会返回错误信息
例2
func main() {
s := []int{1, 2, 3, 4, 5}
m := min(s...)
fmt.Println(m) // invalid operation: invalid use of ... with built-in min
}
传入切片类型依旧报错
例3
func main() {
var x int
m := min(x)
fmt.Println(m) // 0
}
当给函数传递一个参数的时候,返回的结果和入参的值相等
例4
func main() {
var x, y int = 1, 2
m := min(x, y)
fmt.Println(m) // 1
}
同类型比较输出较小的那个
例5
func main() {
c := min(1, 2.0, 3)
fmt.Printf("%T\t%v\n", c, c) // float64 1
}
当有整形和浮点型做比较的时候,由整型转换为浮点型,然后再做比较,最终输出的是 1。
例6
func main() {
t := min("foo", "bar")
fmt.Println(t) // bar
t1 := min("", "foo", "bar")
fmt.Println(t) // ""
}
字符串的比较用的就是按字典序返回最小字符串,如果有空字符串就返回空字符串
特别提示:
- 整型参数,
min
和max
的参数可以交换和组合。 - 字符串类型参数,
min
和max
的参数逐个字节比较,得出最小/最大的字符串,参数可以交换和组合。 - 浮点型参数
-0.0
和0.0
作为参数,-0.0
小于0.0
;负无穷大,小于任意其它数值;正无穷大,大于任意其它数值。 min
和max
的任意参数是 NaN,则返回结果是NaN
(“not-a-number”) 值。
3、clear函数
先看源码
// The clear built-in function clears maps and slices.
// For maps, clear deletes all entries, resulting in an empty map.
// For slices, clear sets all elements up to the length of the slice
// to the zero value of the respective element type. If the argument
// type is a type parameter, the type parameter's type set must
// contain only map or slice types, and clear performs the operation
// implied by the type argument.
func clear[T ~[]Type | ~map[Type]Type1](t T)
我们可以看见,clear函数的参数也是泛型函数,入参为map
、slice
,如果是 map
,则删除 map
中的所有元素,返回一个空 map
;如果是 slice
,则将 slice
中的所有元素改为切片类型的零值。
例1
func main() {
s := []int{1, 2, 3}
fmt.Printf("len=%d\t s=%+v\n", len(s), s) // len=3 s=[1 2 3]
clear(s)
fmt.Printf("len=%d\t s=%+v\n", len(s), s) // len=3 s=[0 0 0]
}
可以看出,长度不变,所有元素变为切片的零值
例2
func main() {
m := map[string]int{"go": 100, "php": 80}
fmt.Printf("len=%d\tm=%+v\n", len(m), m) // len=2 m=map[go:100 php:80]
clear(m)
fmt.Printf("len=%d\tm=%+v\n", len(m), m) // len=0 m=map[]
}
使用clear删除map的时候吧map里面的元素都删除了,长度变为0了。
在项目开发中,我们可以使用函数 clear
删除 map
中的元素,替代通过循环遍历调用 delete
删除 map
中的元素;使用函数 clear
将 slice
中的元素的值修改为切片类型的零值,替代通过循环遍历修改切片中的元素的值为切片类型的零值。