前言
写过PHP的同学都晓得 PHP的数组Array十分好用,特地灵便。
我在写PHP之前应用Java做安卓开发,在接触PHP的数组Array之后,直呼太香了!
而在学习Go基础知识的时候理解到Go的数组和PHP的数组并不一样;从肯定水平上讲,Go的slice切片类型和PHP的数组array比拟像(不固定长度、援用类型、动静扩容等),然而在开发应用中远远不像PHP的array灵便。
初识GoFrame
最近在应用基于Go语言的GoFrame框架撸我的项目,发现GoFrame封装的garray居然比PHP的array还要好用。
近期曾经更新了一系列GoFrame的文章,下文将GoFrame简称为gf。
gf框架有个特点,提供的组件根本都反对设置并发平安开关。显然PHP是不反对并发平安开关的,PHP的数组是并发平安的。PHP-FPM是阻塞的单线程模型,PHP-FPM每个过程里只有一个线程,一个过程同时只能服务一个客户端。
garray特点简介
- garray反对int/string/interface{}三种罕用的数据类型。
- garray反对一般数组和排序数组,一般数组的构造体名称定义为Array格局,排序数组的构造体名称定义为SortedArray格局,如下:Array, intArray, StrArray,SortedArray, SortedIntArray, SortedStrArray
- 其中排序数组SortedArray,须要给定排序比拟办法,在工具包gutil中也定义了很多ComparatorXXX的比拟办法,用起来很不便。当然也反对自定义排序形式。
根本应用
package mainimport ( "fmt" "github.com/gogf/gf/container/garray")func main() { //创立并发平安的int型数组 a := garray.NewIntArray(true) //增加数组项 for i := 0; i < 10; i++ { a.Append(i) } // 打印后果: fmt.Println(a) //"[0,1,2,3,4,5,6,7,8,9]" fmt.Println("数组长度:", a.Len()) fmt.Println("数组的值:", a.Slice()) fmt.Println((a.Get(5))) //依据索引取值 返回值和是否取到了值 5 true // 在指定索引前后插入值 _ = a.InsertAfter(9, 10) _ = a.InsertBefore(0, -1) fmt.Println(a.Slice()) // 搜寻数据项,返回对应的索引 fmt.Println("搜寻值,返回对应索引:", a.Search(5)) // 删除 a.Remove(0) fmt.Println(a.Slice()) // 并发平安 写锁操作 a.LockFunc(func(array []int) { //将最初一项的值改为100 array[len(array)-1] = 100 }) fmt.Println(a) //"[0,1,2,3,4,5,6,7,8,9,100]" // 并发平安 读锁操作 a.RLockFunc(func(array []int) { fmt.Println(array[len(array)-1]) //100 }) // 清空数组 a.Clear() fmt.Println("清空数组之后:", a.Slice())}
打印后果
数组出栈
- 数组出栈应用Pop*关键字
- 数组能够按程序出栈,而gf提供的另外一个数据类型gmap的pop*办法是随机出栈 (关注我,会在后续的文章中更新阐明)
- garray中随机出栈,咱们能够应用rand()或者popRand()
package mainimport ( "fmt" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g")//数组出栈 pop 数组能够按程序出栈 map的pop是随机出栈func main() { a := garray.NewFrom([]interface{}{1, 2, 3, 4, 5, 6}) fmt.Println(a.PopLeft()) fmt.Println(a.PopLefts(2)) fmt.Println(a.PopRight()) fmt.Println(a.PopRights(2)) fmt.Println(a) //全副出栈后 数组为空 /** 打印后果: 1 true [2 3] 6 true [4 5] [] */ // 有什么方法能像map一样随机出栈呢? 在garray中咱们应用rand()或者popRand() a1 := garray.NewFrom(g.Slice{1, 2, 3, 4, 5, 6, 7}) fmt.Println("----------") fmt.Println(a1.Rand()) //随机取值 fmt.Println(a1.PopRands(2)) //随机出栈 fmt.Println(a1)}
蕴含判断
- 留神:Contains()是辨别大小写
- 空值过滤应用:FilterEmpty
- nil过滤应用:FilterNil
package mainimport ( "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g")//蕴含 contains 辨别大小写func main() { var a garray.Array a.Append("a") g.Dump(a.Contains("a")) //true g.Dump(a.Contains("A")) //false // 空值过滤 a1 := garray.NewFrom([]interface{}{0, 1, "2", nil, false, g.Slice{}, "王中阳"}) a2 := garray.NewFrom([]interface{}{0, 1, "2", nil, false, g.Slice{}, "王中阳"}) g.Dump("empty过滤:", a1.FilterEmpty()) //empty过滤:"[1,2,"王中阳"]" g.Dump("nil过滤:", a2.FilterNil()) //nil过滤:"[0,1,2,"false","[]","王中阳"]" a3 := garray.NewFrom([]interface{}{1, 2, 3, 4, 5, 6, 7}) g.Dump("数组翻转:", a3.Reverse()) g.Dump("数组随机排序:", a3.Shuffle())}
打印后果
排序数组
- 咱们能够自定义NewSortedArray的排序规定,以实现是升序数组还是降序数组;
- 排序数组还有唯一性校验的性能:garray.SetUnique(true)
- gf框架的gutil工具包定义好了罕用的排序规定
package mainimport ( "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/util/gutil")//咱们能够自定义NewSortedArray的排序规定,以实现是升序数组还是降序数组;排序数组还有唯一性校验的性能func main() { //自定义排序数组:降序排列 a := garray.NewSortedArray(func(a, b interface{}) int { if a.(int) < b.(int) { return 1 } if a.(int) > b.(int) { return -1 } return 0 }) // 排序规格能够应用gutil中定义好的 a.Add(2) //数组的赋值用add map的赋值用set a.Add(1) a.Add(3) g.Dump("a:", a) //打印后果:"[3,2,1]" //升序数组 a2 := garray.NewSortedArray(gutil.ComparatorInt) a2.Add(2) a2.Add(1) a2.Add(3) g.Dump("a2:", a2) // 增加反复元素 a2.Add(2) g.Dump("a2增加反复元素后:", a2) a2.SetUnique(true) //设置不容许反复元素 g.Dump("a2设置不容许反复元素之后:", a2)}
打印后果
join、chunk、merge
- 数据项串联是相当罕用的场景,比方多个id以逗号分隔入库存储,咱们应用join关键字即可
- garray反对将一个数组拆分成指定数量的二维数组,应用chunk关键字
- garray反对应用merge关键字合并数组
package mainimport ( "fmt" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g")func main() { //join 串联 罕用于逗号宰割 a := garray.NewFrom(g.Slice{1, 2, 3, 4, 5}) fmt.Println("串联后果:", a.Join("_")) //1_2_3_4_5 //数组拆分 chunk fmt.Println("数组拆分:", a.Chunk(2)) //[[1 2] [3 4] [5]] // 数组合并 能够合并数组 也能够合并slice(原生切片和g.Slice都反对) a1 := garray.NewFrom(g.Slice{1, 2}) a2 := garray.NewFrom(g.Slice{3, 4}) s1 := g.Slice{5, 6} s2 := []string{"7", "8"} s3 := []int{9, 0} a1.Merge(a2) a1.Merge(s1) a1.Merge(s2) a1.Merge(s3) fmt.Println("合并后果:", a1) // [1,2,3,4,5,6,7,8,9,0]}
打印后果:
遍历
- garray人造反对升序遍历和降序遍历
- 函数Iterator()是IteratorAsc()的别名
package mainimport ( "fmt" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g")//数组遍历 iteratefunc main() { a := garray.NewFrom(g.Slice{"a", "b", "c"}) fmt.Println("升序遍历后果") a.Iterator(func(k int, v interface{}) bool { fmt.Printf("%v,%v \n", k, v) return true }) // 数组倒序遍历 fmt.Println("倒序遍历后果:") a.IteratorDesc(func(k int, v interface{}) bool { fmt.Printf("%v,%v \n", k, v) return true })}
打印后果
遍历批改 walk函数
十分好用!!!
看到这个办法,更深信了我一个观点:GF的作者肯定写了几年PHP。
package mainimport ( "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/util/gconv")//walk遍历批改 批改数组的值func main() { var a garray.Array tables := g.Slice{"user", "user_detail"} a.Append(tables...) prefix := "gf_" a.Walk(func(value interface{}) interface{} { return prefix + gconv.String(value) }) g.Dump(a)}
打印后果
序列化和反序列化
- 这里重点提一下:gf container容器包下的对象都实现对原生json包的反对,都反对序列化和反序列化。
- gf非常重视对序列化的反对,gmap、glist、gqueue、gset、gtree...等gf组件,都是反对序列化和反序列化的。
package mainimport ( "encoding/json" "fmt" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g")//gf container容器包下的对象都实现对原生json包的反对,即都反对序列化和反序列化func main() { //序列化 type student struct { Name string Age int Scores *garray.IntArray } s := student{ Name: "王中阳", Age: 28, Scores: garray.NewIntArrayFrom([]int{100, 98}), } bytes, _ := json.Marshal(s) g.Dump(bytes) //{"Name":"王中阳","Age":28,"Scores":[100,98]} //反序列化 data := []byte(`{"Name":"王中阳","Age":28,"Scores":[100,98]}`) s2 := student{} _ = json.Unmarshal(data, &s2) fmt.Println(s2) //{王中阳 28 [100,98]}}
打印后果
总结
综上咱们理解到:
- garray反对设置并发平安开关
- 反对排序数组
- 反对数组出栈、蕴含判断、join、chunk、merge等罕用的工具办法
- 人造反对升序遍历、遍历批改
- 人造反对序列化和反序列化
大家是不是显著感觉到GoFrame的garray比PHP的array还要好用。
更加深信GoFrame的作者是写过PHP的
小伙伴们还想看哪些内容,欢送在评论区留言。
本文参加了思否技术征文,欢送正在浏览的你也退出。