首頁 > 軟體

GoFrame框架garray對比PHP的array優勢

2022-06-11 14:00:19

寫過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。感興趣的同學可以關注我的專欄:Go語言學習專欄 ,目前已經更新了86篇原創文章,獲得了176位同學的關注。

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 main
import (
   "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 main
import (
   "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 main
import (
   "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 main
import (
   "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 main
import (
   "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 main
import (
   "fmt"
   "github.com/gogf/gf/container/garray"
   "github.com/gogf/gf/frame/g"
)
//陣列遍歷 iterate
func 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 main
import (
   "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非常重視對序列化的支援,Go學習專欄 文章中介紹了gmap、glist、gqueue、gset、gtree...等gf元件,都是支援序列化和反序列化的。

列印結果

總結

綜上我們瞭解到:

  • garray支援設定並行安全開關
  • 支援排序陣列
  • 支援陣列出棧、包含判斷、join、chunk、merge等常用的工具方法
  • 天然支援升序遍歷、遍歷修改
  • 天然支援序列化和反序列化

大家是不是明顯感覺到GoFrame的garray比PHP的array還要好用。

更加堅信GoFrame的作者是寫過PHP的

以上就是GoFrame框架garray對比PHP的array優勢的詳細內容,更多關於GoFrame框架garray優勢的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com