前言

写过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特点简介

  1. garray反对int/string/interface{}三种罕用的数据类型。
  2. garray反对一般数组和排序数组,一般数组的构造体名称定义为Array格局,排序数组的构造体名称定义为SortedArray格局,如下:Array, intArray, StrArray,SortedArray, SortedIntArray, SortedStrArray
  3. 其中排序数组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())}

打印后果

数组出栈

  1. 数组出栈应用Pop*关键字
  2. 数组能够按程序出栈,而gf提供的另外一个数据类型gmap的pop*办法是随机出栈 (关注我,会在后续的文章中更新阐明)
  3. 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)}

蕴含判断

  1. 留神:Contains()是辨别大小写
  2. 空值过滤应用:FilterEmpty
  3. 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())}

打印后果

排序数组

  1. 咱们能够自定义NewSortedArray的排序规定,以实现是升序数组还是降序数组;
  2. 排序数组还有唯一性校验的性能:garray.SetUnique(true)
  3. 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

  1. 数据项串联是相当罕用的场景,比方多个id以逗号分隔入库存储,咱们应用join关键字即可
  2. garray反对将一个数组拆分成指定数量的二维数组,应用chunk关键字
  3. 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]}

打印后果:

遍历

  1. garray人造反对升序遍历和降序遍历
  2. 函数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)}

打印后果

序列化和反序列化

  1. 这里重点提一下:gf container容器包下的对象都实现对原生json包的反对,都反对序列化和反序列化。
  2. 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]}}

打印后果

总结

综上咱们理解到:

  1. garray反对设置并发平安开关
  2. 反对排序数组
  3. 反对数组出栈、蕴含判断、join、chunk、merge等罕用的工具办法
  4. 人造反对升序遍历、遍历批改
  5. 人造反对序列化和反序列化

大家是不是显著感觉到GoFrame的garray比PHP的array还要好用。

更加深信GoFrame的作者是写过PHP的

小伙伴们还想看哪些内容,欢送在评论区留言。

本文参加了思否技术征文,欢送正在浏览的你也退出。