GO-knowledge
前记
用来记录一些go的进阶知识点
常用的一些函数
- 统计字符串长度: len(str)
- 字符串遍历: []rune(str)
- 字符串转整数: strconv.Atoi("12")
- 整数转字符串: strconv.Itoa(12)
- 字符串转[]byte: var bytes = []byte("hello")
- []byte转字符串: var str = string([]byte{98,97})
- 查找子串是否在指定的字符串中: strings.Contains("seafood","foo") //true
- 统计一个字符串有几个指定的子串: strings.Count("ceheese", "e") //4
- 不区分大小写的字符串比较: strings.EqualFold("abc","Abc") //true
- 返回子串在字符串第一次出现的 index 值,如果没有返回-1: strings.Index("NLT_abc", "abc") //4
- 返回子串在字符串最后一次出现的 index 值,如果没有返回-1: strings.LastIndex("NLT_abc", "abc") //4
- 将指定的子串替换成另外一个子串: strings.Replace("go go hello", "go", "go 语言", n) n 可以指定你希望替换几个, 如果 n=-1 表示全部替换。将"go go hello"中的所有的n个"go"替换为"go语言"。
- 按照指定的某个字符,为分割标识,将一个字符串拆分成字符串数组:strings.Split("hello,world,ok", ",")
- 按照指定的某个字符为连接符,将一个字符串数组合并成字符串:strings.Join([]string{"hello","world","ok"}, ",")
- 将字符串的字母进行大小写的转换: strings.ToLower("Go") // go
- 将字符串的字母进行大小写的转换: strings.ToUpper("Go") // GO
- 将字符串左右两边的空格去掉: strings.TrimSpace(" tn a lone gopher ntrn ")
- 将字符串左右两边指定的字符去掉: strings.Trim("! hello! ", " !") // ["hello"] //将左右两边 !和 " "去掉
- 判断字符串是否以指定的字符串开头: strings.HasPrefix("ftp://192.168.10.1", "ftp") //true
- copy函数,将第二个slice里的元素拷贝到第一个slice里,拷贝的长度为两个slice中长度较小的长度值,不支持数组:
go
s1 := []int{1,2,3}
s2 := []int{4,5,6,7,8,9}
// s1长度比s2长度短,以len(s1)=3的长度复制
// 所以会将4,5,6覆盖掉1,2,3
// 所以下面s1打印出来为[4, 5, 6]
// copy函数会返回复制的长度
n := copy(s1, s2)
- go在1.21版本开始内置了max、min函数以及clear函数
- clear函数
该函数接收一个参数 t,用于清空变量 t (类型为 slice 或 map) 中的元素。
* 如果传递的是切片类型变量,则会将切片的所有元素赋值为该切片类型的零值;
* 如果传递的是 map 类型变量,则会清空map 类型变量的元素;
* 如果传递的是自定义泛型类型(例如 type MySlice[T any] []T),则类型集中所有类型必须是 slice 或 map。
math库
有一些比较常用的函数
- math.Abs()
- math.MaxInt / math.MinInt 整数的无穷大和负无穷大
- math.Inf(1) / math.Inf(-1) 浮点数的无穷大和负无穷大
sort函数
内置的切片排序包。直接改变原数组。
- sort.Ints() //传入Int数组
- sort.Strings() //传入String数组
- sort.Float64s() //传入float64数组
- sort.Slice() //传入两个参数:第一个为需要排序的数据,第二个为对元素的回调函数,感觉和js的reduce函数很像
- sort.Stable() //稳定排序
go
//从大到小排序
sort.Slice(tmp,func(i,j int){ //tmp是要排序的切片
return tmp[i]<tmp[j]
})
注意
由于没有自带的从大到小排序,因此可以使用slice自定义排序方式
- sort.Sort(sort.Reverse(sort.IntSlice(nums))) //将数组从大到校排序
sort.IntSlice(nums) 将普通的 []int 切片 nums 转换为 sort.IntSlice 类型
sort.IntSlice 是一个实现了 sort.Interface 接口的类型(包含 Len(), Less(i, j int) bool, Swap(i, j int) 方法)
默认情况下,IntSlice 的 Less() 方法定义为 p[i] < p[j],即按升序排序
sort.Reverse(...) 接收一个实现了 sort.Interface 的类型(这里是 IntSlice)
返回一个新的 reverseInterface 类型,它包装了原始接口
关键变化是反转了 Less() 方法的逻辑:
源码分析:
go
// reverse 是一个实现了 sort.Interface 的结构体
type reverse struct {
Interface // 嵌入原始 Interface
}
// 重写 Less 方法实现逻辑反转
func (r reverse) Less(i, j int) bool {
return r.Interface.Less(j, i) // 关键点:调换参数位置
}
// Reverse 返回一个包装后的 Interface
func Reverse(data Interface) Interface {
return &reverse{data}
}
- sort.Sort(...) 对实现了 sort.Interface 的数据进行实际排序,由于 Less() 方法已被反转,结果就是降序排列
我的理解
sort包使用的是快速排序,针对sort.Interface这个类型进行排序,这个接口有Len(),Less(),Swap()三个方法,sort.Reverse使得该类型中的Less结果倒置,然后再进行排序,进而达到想要的从大到小的效果。
new函数和make函数
new用来分配内存,主要用来分配值类型,比如 int/float32/struct。返回的是指针。make也用来分配内存,主要用来分配引用类型,比如 channel/map/slice。返回引用类型本身。
区别:
- new 返回指针,make 返回引用类型
- new 没有参数,make 需要指定类型
- make 返回初始化后可以直接使用的对象,new 返回还需要初始化的指针
- make 只用于 slice、map、channel 等内置引用类型,new 可用于任意类型
append函数
非常重要的函数
append操作数组,可以追加元素、切片,删除元素
- 追加元素
go
slice = append(slice,elem1,elem2)
append括号内,第一个参数slice后可以加多个参数。
- 追加切片
go
slice = append(slice,anotherSlice...)
通过...拆分切片
- 删除元素
go
s = append( s[:index], s[index+1:] )
但是比较低效,下面的方法会更为高效
go
func DeleteSlice3(a []int, elem int) []int {
j := 0
for _, v := range a {
if v != elem {
a[j] = v
j++
}
}
return a[:j]
}
装饰器模式
go
// 装饰器模式
type Handler func(http.ResponseWriter, *http.Request)
// 等于是一个中间键,将handler包起来了
func Logger(handler Handler) Handler {
return func(w http.ResponseWriter, r *http.Request) {
start_time := time.Now()
handler(w, r)
log.Printf("url:%v,duration:%v", r.URL, time.Since(start_time))
}
}