GoFrame框架garray對比PHP的array優(yōu)勢
寫過PHP的同學都知道 PHP的數(shù)組Array非常好用,特別靈活。
我在寫PHP之前使用Java做安卓開發(fā),在接觸PHP的數(shù)組Array之后,直呼太香了!
而在學習Go基礎(chǔ)知識的時候了解到Go的數(shù)組和PHP的數(shù)組并不一樣;從一定程度上講,Go的slice切片類型和PHP的數(shù)組array比較像(不固定長度、引用類型、動態(tài)擴容等),但是在開發(fā)使用中遠遠不像PHP的array靈活。
初識GoFrame
最近在使用基于Go語言的GoFrame框架擼項目,發(fā)現(xiàn)GoFrame封裝的garray竟然比PHP的array還要好用。
近期已經(jīng)更新了一系列GoFrame的文章,下文將GoFrame簡稱為gf。感興趣的同學可以關(guān)注我的專欄:Go語言學習專欄 ,目前已經(jīng)更新了86篇原創(chuàng)文章,獲得了176位同學的關(guān)注。
gf框架有個特點,提供的組件基本都支持設(shè)置并發(fā)安全開關(guān)。顯然PHP是不支持并發(fā)安全開關(guān)的,PHP的數(shù)組是并發(fā)安全的。PHP-FPM是阻塞的單線程模型,PHP-FPM每個進程里只有一個線程,一個進程同時只能服務(wù)一個客戶端。
garray特點簡介
- garray支持int/string/interface{}三種常用的數(shù)據(jù)類型。
- garray支持普通數(shù)組和排序數(shù)組,普通數(shù)組的結(jié)構(gòu)體名稱定義為Array格式,排序數(shù)組的結(jié)構(gòu)體名稱定義為SortedArray格式,如下:Array, intArray, StrArray,SortedArray, SortedIntArray, SortedStrArray
- 其中排序數(shù)組SortedArray,需要給定排序比較方法,在工具包gutil中也定義了很多ComparatorXXX的比較方法,用起來很方便。當然也支持自定義排序方式。
基本使用
package main import ( "fmt" "github.com/gogf/gf/container/garray" ) func main() { //創(chuàng)建并發(fā)安全的int型數(shù)組 a := garray.NewIntArray(true) //添加數(shù)組項 for i := 0; i < 10; i++ { a.Append(i) } // 打印結(jié)果: fmt.Println(a) //"[0,1,2,3,4,5,6,7,8,9]" fmt.Println("數(shù)組長度:", a.Len()) fmt.Println("數(shù)組的值:", a.Slice()) fmt.Println((a.Get(5))) //根據(jù)索引取值 返回值和是否取到了值 5 true // 在指定索引前后插入值 _ = a.InsertAfter(9, 10) _ = a.InsertBefore(0, -1) fmt.Println(a.Slice()) // 搜索數(shù)據(jù)項,返回對應(yīng)的索引 fmt.Println("搜索值,返回對應(yīng)索引:", a.Search(5)) // 刪除 a.Remove(0) fmt.Println(a.Slice()) // 并發(fā)安全 寫鎖操作 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]" // 并發(fā)安全 讀鎖操作 a.RLockFunc(func(array []int) { fmt.Println(array[len(array)-1]) //100 }) // 清空數(shù)組 a.Clear() fmt.Println("清空數(shù)組之后:", a.Slice()) }
打印結(jié)果
數(shù)組出棧
- 數(shù)組出棧使用Pop*關(guān)鍵字
- 數(shù)組可以按順序出棧,而gf提供的另外一個數(shù)據(jù)類型gmap的pop*方法是隨機出棧 (關(guān)注我,會在后續(xù)的文章中更新說明)
- garray中隨機出棧,我們可以使用rand()或者popRand()
package main import ( "fmt" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" ) //數(shù)組出棧 pop 數(shù)組可以按順序出棧 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) //全部出棧后 數(shù)組為空 /** 打印結(jié)果: 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()是區(qū)分大小寫
- 空值過濾使用:FilterEmpty
- nil過濾使用:FilterNil
package main import ( "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" ) //包含 contains 區(qū)分大小寫 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("數(shù)組翻轉(zhuǎn):", a3.Reverse()) g.Dump("數(shù)組隨機排序:", a3.Shuffle()) }
打印結(jié)果
排序數(shù)組
- 我們可以自定義NewSortedArray的排序規(guī)則,以實現(xiàn)是升序數(shù)組還是降序數(shù)組;
- 排序數(shù)組還有唯一性校驗的功能:garray.SetUnique(true)
- gf框架的gutil工具包定義好了常用的排序規(guī)則
package main import ( "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/util/gutil" ) //我們可以自定義NewSortedArray的排序規(guī)則,以實現(xiàn)是升序數(shù)組還是降序數(shù)組;排序數(shù)組還有唯一性校驗的功能 func main() { //自定義排序數(shù)組:降序排列 a := garray.NewSortedArray(func(a, b interface{}) int { if a.(int) < b.(int) { return 1 } if a.(int) > b.(int) { return -1 } return 0 }) // 排序規(guī)格可以使用gutil中定義好的 a.Add(2) //數(shù)組的賦值用add map的賦值用set a.Add(1) a.Add(3) g.Dump("a:", a) //打印結(jié)果:"[3,2,1]" //升序數(shù)組 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) //設(shè)置不允許重復元素 g.Dump("a2設(shè)置不允許重復元素之后:", a2) }
打印結(jié)果
join、chunk、merge
- 數(shù)據(jù)項串聯(lián)是相當常用的場景,比如多個id以逗號分隔入庫存儲,我們使用join關(guān)鍵字即可
- garray支持將一個數(shù)組拆分成指定數(shù)量的二維數(shù)組,使用chunk關(guān)鍵字
- garray支持使用merge關(guān)鍵字合并數(shù)組
package main import ( "fmt" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" ) func main() { //join 串聯(lián) 常用于逗號分割 a := garray.NewFrom(g.Slice{1, 2, 3, 4, 5}) fmt.Println("串聯(lián)結(jié)果:", a.Join("_")) //1_2_3_4_5 //數(shù)組拆分 chunk fmt.Println("數(shù)組拆分:", a.Chunk(2)) //[[1 2] [3 4] [5]] // 數(shù)組合并 可以合并數(shù)組 也可以合并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("合并結(jié)果:", a1) // [1,2,3,4,5,6,7,8,9,0] }
打印結(jié)果:
遍歷
garray天然支持升序遍歷和降序遍歷
函數(shù)Iterator()是IteratorAsc()的別名
package main import ( "fmt" "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" ) //數(shù)組遍歷 iterate func main() { a := garray.NewFrom(g.Slice{"a", "b", "c"}) fmt.Println("升序遍歷結(jié)果") a.Iterator(func(k int, v interface{}) bool { fmt.Printf("%v,%v \n", k, v) return true }) // 數(shù)組倒序遍歷 fmt.Println("倒序遍歷結(jié)果:") a.IteratorDesc(func(k int, v interface{}) bool { fmt.Printf("%v,%v \n", k, v) return true }) }
打印結(jié)果
遍歷修改 walk函數(shù)
非常好用?。。?/p>
看到這個方法,更堅信了我一個觀點:GF的作者一定寫了幾年P(guān)HP。
package main import ( "github.com/gogf/gf/container/garray" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/util/gconv" ) //walk遍歷修改 修改數(shù)組的值 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) }
打印結(jié)果
序列化和反序列化
這里重點提一下:gf container容器包下的對象都實現(xiàn)對原生json包的支持,都支持序列化和反序列化。
gf非常重視對序列化的支持,Go學習專欄 文章中介紹了gmap、glist、gqueue、gset、gtree...等gf組件,都是支持序列化和反序列化的。
打印結(jié)果
總結(jié)
綜上我們了解到:
- garray支持設(shè)置并發(fā)安全開關(guān)
- 支持排序數(shù)組
- 支持數(shù)組出棧、包含判斷、join、chunk、merge等常用的工具方法
- 天然支持升序遍歷、遍歷修改
- 天然支持序列化和反序列化
大家是不是明顯感覺到GoFrame的garray比PHP的array還要好用。
更加堅信GoFrame的作者是寫過PHP的
以上就是GoFrame框架garray對比PHP的array優(yōu)勢的詳細內(nèi)容,更多關(guān)于GoFrame框架garray優(yōu)勢的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang給函數(shù)參數(shù)設(shè)置默認值的幾種方式小結(jié)(函數(shù)參數(shù)默認值
在日常開發(fā)中我們有時候需要使用默認設(shè)置,下面這篇文章主要給大家介紹了關(guān)于golang給函數(shù)參數(shù)設(shè)置默認值的幾種方式小結(jié)的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-01-01Golang執(zhí)行g(shù)o get私有庫提示"410 Gone" 的問題及解決辦法
這篇文章主要介紹了Golang執(zhí)行g(shù)o get私有庫提示”410 Gone“ 解決辦法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02執(zhí)行g(shù)o?build報錯go:?go.mod?file?not?found?in?current?dir
本文主要為大家介紹了執(zhí)行g(shù)o build報錯go:?go.mod?file?not?found?in?current?directory?or?any?parent?directory解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06