当前位置: 首页 > 科技观察

GoFrame数组优于PHP数组!?

时间:2023-03-14 18:47:52 科技观察

前言写过PHP的同学都知道,PHP的Array非常好用,非常灵活。在我写PHP之前,我是用Java做Android开发的。接触到PHP的Array后,我说太香了!在学习Go基础的时候,了解到Go的数组和PHP的数组不一样;Go的切片类型在一定程度上类似于PHP的array数组(不定长、引用类型、动态扩展等),但在开发和使用上远不如PHP的数组灵活。初识GoFrame,最近使用了基于Go语言的GoFrame框架项目,发现GoFrame封装的garray甚至比PHP数组更易用。最近更新了一系列GoFrame文章,GoFrame以下简称gf。感兴趣的同学可以关注我的专栏:Go语言学习专栏,更新了120多篇原创文章,吸引了700多位同学的关注。gf框架有个特点,提供的组件基本都支持设置并发安全开关。显然PHP不支持并发安全开关,PHP数组是并发安全的。PHP-FPM是一个阻塞的单线程模型。PHP-FPM的每个进程只有一个线程,一个进程一次只能为一个客户端服务。Garray特性介绍Garray支持三种常用的数据类型:int/string/interface{}。Garray支持普通数组和排序数组。普通数组的结构名定义为Array格式,排序数组的结构名定义为SortedArray格式,如下:Array,intArray,StrArray,SortedArray,SortedIntArray,SortedStrArray。需要给出排序数组SortedArray工具包gutil中定义了很多ComparatorXXX比较方法,使用起来非常方便。当然也支持自定义排序方式。基本上使用packagemainimport("fmt""github.com/gogf/gf/container/garray")funcmain(){//创建并发安全的int数组a:=garray.NewIntArray(true)//添加数组项因为我:=0;我<10;i++{a.Append(i)}//打印结果:fmt.Println(a)//[0,1,2,3,4,5,6,7,8,9]"fmt.Println("Arraylength:",a.Len())fmt.Println("Arrayvalue:",a.Slice())fmt.Println((a.Get(5)))//根据索引值返回值以及是否获取到值5true//在指定索引前后插入值_=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){//将最后一项的值改为100array[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()packagemainimport("fmt""github.com/gogf/gf/container/garray""github.com/gogf/gf/frame/g")//数组出栈pop数组可以按顺序出栈map的pop随机出栈funcmain(){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)//全部弹出后数组为空/**打印结果:1true[23]6true[45][]*///有没有有什么办法可以像地图一样随机弹出堆栈?在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()它区分大小写。空值过滤使用:FilterEmptynil过滤使用:FilterNilpackagemainimport("github.com/gogf/gf/container/garray""github.com/gogf/gf/frame/g")//containscase-sensitivefuncmain(){varagarray.Arraya.Append("a")g.Dump(a.Contains("a"))//trueg.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("emptyfilter:",a1.FilterEmpty())//emptyfilter:"[1,2,"王中阳"]"g.Dump("nilfilter:",a2.FilterNil())//nilfilter:"[0,1,2,"false","[]",王中阳"]"a3:=garray.NewFrom([]interface{}{1,2,3,4,5,6,7})g.Dump("数组翻转:",a3.Reverse())g.Dump("Arrayrandomsorting:",a3.Shuffle())}打印结果排序数组我们可以自定义NewSortedArray的排序规则,实现是升序还是降序数组;排序数组还有唯一性验证的功能:garray.SetUnique(true)gf框架的gutil工具包定义了常用的排序规则包mainimport("github.com/gogf/gf/container/garray""github.com/gogf/gf/frame/g""github.com/gogf/gf/util/gutil")//我们可以自定义NewSortedArray的排序规则,实现是升序数组还是降序数组;排序数组还有唯一性验证的功能funcmain(){//自定义排序数组:降序排列a:=garray.NewSortedArray(func(a,binterface{})int{ifa.(int)b.(int){return-1}return0})//排序规范可以使用guta.Add(2)definedinil//数组赋值使用addmap赋值使用seta.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关键字合并数组.com/gogf/gf/frame/g")funcmain(){//连接连接通常用于逗号分割a:=garray.NewFrom(g.Slice{1,2,3,4,5})fmt.Println("Concatenationresult:",a.Join("_"))//1_2_3_4_5//Arraysplitchunkfmt.Println("Arraysplit:",a.Chunk(2))//[[12][34][5]]//数组合并可以合并数组或者切片(原生切片和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()的别名packagemainimport("fmt""github.com/gogf/gf/container/garray""github.com/gogf/gf/frame/g")//数组遍历iteratefuncmain(){a:=garray.NewFrom(g.Slice{"a","b","c"})fmt.Println("升序遍历结果")a.Iterator(func(kint,vinterface{})bool{fmt.Printf("%v,%v\n",k,v)returntrue})//倒序遍历数组fmt.Println("逆序遍历结果:")a.IteratorDesc(func(kint,vinterface{})bool{fmt.Printf("%v,%v\n",k,v)returntrue})}print结果遍历修改行走功能非常好用!!!看到这个方法,更加坚定了自己的观点:GF的作者肯定是写了几年PHP的packagemainimport("github.com/gogf/gf/container/garray""github.com/gogf/gf/frame/g""github.com/gogf/gf/util/gconv")//遍历修改funcmain(){varagarray.Arraytables:=g.Slice{"user","user_detail"}a.Append(tables...)prefix:="gf_"a.Walk(func(valueinterface{})interface{}{returnprefix+gconv.String(value)})g.Dump(a)}打印结果序列化与反序列化这里有一个重点要提一下:gf容器容器包下的对象实现原生json包支持,既支持序列化也支持反序列化。gf非常重视对连载的支持。Go学习专栏文章介绍了gmap、glist、gqueue、gset、gtree等gf组件,它们都支持序列化和反序列化。packagemainimport("encoding/json""fmt""github.com/gogf/gf/container/garray""github.com/gogf/gf/frame/g")//gf容器包下的对象都实现了原生json包的支持,即同时支持序列化和反序列化funcmain(){//序列化类型studentstruct{NamestringAgeintScores*garray.IntArray}s:=student{Name:"WangZhongyang",年龄:28,分数:garray.NewIntArrayFrom([]int{100,98}),}bytes,_:=json.Marshal(s)g.Dump(bytes)//{"Name":"WangZhongyang","Age":28,"Scores":[100,98]}//反序列化数据:=[]byte(`{"Name":"WangZhongyang","Age":28,"Scores":[100,98]}`)s2:=student{}_=json.Unmarshal(data,&s2)fmt.Println(s2)//{王中阳28[100,98]}}打印结果总结综上所述,我们理解garray支持设置并发安全开关支持排序数组支持弹出数组,包括判断、连接、分块、合并等常用工具和方法自然支持ts升序遍历,遍历修饰天然支持序列化和反序列化数组就更加好用了。本文转载自微信公众号《程序员的升级打怪之旅》,作者“王中阳围棋”,可通过以下二维码关注。转载本文请联系《程序员升级打怪之旅》公众号。