欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PHP轉(zhuǎn)Go之?dāng)?shù)組的正確使用詳解

 更新時(shí)間:2023年09月17日 11:38:06   作者:全Neng攻城獅  
這篇文章主要為大家對比一下PHP中的Array和Golang中的 Array&Slice&Map,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

本文概要

思維速轉(zhuǎn),PHP Array -> Go Array or Slice or Map

底層實(shí)現(xiàn)的異同

使用中的注意事項(xiàng)及坑坑

  • 如何選擇 Array 和 Slice
  • 值傳遞和引用傳遞的坑
  • Map 的無序
  • 并發(fā)安全性

一、思維速轉(zhuǎn)

PHP 中 Array 實(shí)在是太好用了,即可以聲明為索引數(shù)組,又可以聲明為關(guān)聯(lián)數(shù)組;但是在 Golang 中,被拆解成了多個(gè)數(shù)據(jù)類型,其中索引數(shù)組與 Array/Slice 更貼近,而關(guān)聯(lián)數(shù)組更貼近于 Map

// 索引數(shù)組
$colors = array("red", "green", "blue");  
// Go Array: [3]string{"red", "green", "blue"} // 固定長度
// Go Slice: []string{"red", "green", "blue"}
// 關(guān)聯(lián)數(shù)組
$person = array(
    "first_name" => "John",
    "last_name" => "Doe",
    "age" => 30
);
// 對比 Golang Map
person := map[string]string{
    "first_name": "John",
    "last_name": "Doe",
    "age": "30",   // 特別注意強(qiáng)類型下 map 中值部分無法存放不同類型的數(shù)據(jù)
}

二、底層實(shí)現(xiàn)的異同

PHP 的語法上屏蔽了索引數(shù)組和關(guān)聯(lián)數(shù)組,底層實(shí)現(xiàn)均基于 HashTable 完成,但是對于 Golang 來說,不同的類型實(shí)現(xiàn)是略有差異的;

Array 底層實(shí)現(xiàn)

Go 的 Array 一定是預(yù)先確定長度的,故底層分配的是固定連續(xù)內(nèi)存,變量在聲明后,直接指向數(shù)組存儲的內(nèi)存地址,所以讀取會非常高效

arr := [3]int32{1,2,3}
fmt.Println(&arr[0],&arr[1],&arr[2])
// Output: 可以看到每個(gè)元素偏移剛好是 4 個(gè)字節(jié)
0xc0000a6030 0xc0000a6034 0xc0000a6038

特別注意,對于[3]string 字符串?dāng)?shù)組來說,string 實(shí)際上是存放在獨(dú)立的內(nèi)存中的,所以數(shù)組中保存的是字符串地址,所以打印出來的地址偏移是 16 個(gè)字節(jié)(string 底層數(shù)據(jù)結(jié)構(gòu)包括一個(gè)指向字符串真實(shí)地址的指針,以及一個(gè)字符串長度的值)

注意,所有這些字節(jié)偏移均是 64 位機(jī)器上

Slice 底層實(shí)現(xiàn)

Slice 實(shí)際上底層也是引用了數(shù)組的實(shí)現(xiàn),但是它在數(shù)組的上面又封裝了一層數(shù)據(jù)結(jié)構(gòu),當(dāng)我們打印 Slice 中每個(gè)元素的內(nèi)存地址時(shí)你會發(fā)現(xiàn)其每個(gè)元素的偏移規(guī)則與數(shù)組是一致的。差別在于當(dāng)我們打印整個(gè)數(shù)組的指針地址時(shí)會發(fā)現(xiàn)其與數(shù)組第一個(gè)元素的地址是一致的,而 Slice 的不同。

type slice struct {
    array unsafe.Pointer  // 指向底層數(shù)組
    len   int
    cap   int
}
arr := [3]int64{1,2,3}
fmt.Printf("arr : %p \n", &arr)
fmt.Println(&arr,&arr[0],&arr[1],&arr[2])
slice := []int64{1,2,3}
fmt.Printf("slice : %p \n", &slice)
fmt.Println(&slice,&slice[0],&slice[1],&slice[2])
// Output:
arr : 0xc000018120 // 與第一個(gè)元素一致
&[1 2 3] 0xc000018120 0xc000018128 0xc000018130
slice : 0xc000010078 // 指向 Slice 結(jié)構(gòu)體指針,故與第一個(gè)元素內(nèi)存不一致
&[1 2 3] 0xc000018150 0xc000018158 0xc000018160

Slice 實(shí)際上實(shí)現(xiàn)了高效的動態(tài)擴(kuò)容能力,故對比 Array 來說應(yīng)用場景更廣泛

Map 底層實(shí)現(xiàn)

Golang 的 Map 底層實(shí)現(xiàn)也同樣是 HashTable ,相同點(diǎn)是,查找插入效率高,支持動態(tài)擴(kuò)容等,但是 Golang 下的 Map 在遍歷時(shí)是無序的,php 下的關(guān)聯(lián)數(shù)組則是有序的;

關(guān)于 Golang 中 Array,Slice,Map 更詳細(xì)的底層實(shí)現(xiàn)有大量文章分析,這里不再贅述

使用中的注意事項(xiàng)及坑坑

Array 和 Slice 的選擇

Array 在某些場景下的確是使用起來會更高效,所以原則上在某些特別注意性能,且的確是不需要數(shù)據(jù)長度變動的情況下可以選擇 Array,但是,我要特別說明,這種場景極少極少,在日常業(yè)務(wù)系統(tǒng)開發(fā)中,無腦選擇使用 Slice 通常是正確的選擇

值傳遞和引用傳遞

Array 是值傳遞,Slice 和 Map 是引用傳遞,換句話說,Array 將數(shù)據(jù)傳遞到子函數(shù)后在子函數(shù)做任何修改,不會影響父函數(shù)內(nèi)原始數(shù)據(jù),但是 Slice 和 Map 不一樣,子函數(shù)對數(shù)據(jù)的修改會修改原始數(shù)據(jù),所以在上面無腦選擇 Slice 時(shí)要特別注意這一項(xiàng),是否擔(dān)心子函數(shù)意外修改數(shù)據(jù)

Map 的無序的坑

這個(gè)從 PHP 轉(zhuǎn)到 Go 可能無法注意到的一點(diǎn),每次循環(huán) Map 居然可能會得到完全不一樣的順序的結(jié)果,所以要想保證 Map 順序通常需要配合 slice 完成,或者借助第三方庫,比如:https://github.com/iancoleman/orderedmaphttps://github.com/wangjia184/sortedset 但實(shí)際上這種可能也會帶來 json 序列化的坑,所以從接口設(shè)計(jì)上就應(yīng)盡可能避免,對有序要求的盡可能使用 Slice

并發(fā)安全性

Go 是一個(gè)語言級別就支持并發(fā)的語言,但是 Slice 和 Map 都是并發(fā)不安全的類型,所以在并發(fā)操作 Slice 和 Map 時(shí)可能會引起沖突,故要特別注意,修改數(shù)據(jù)時(shí)需要引入 sync.Mutex 互斥鎖 or 利用 channel 完成,Map 還提供了一個(gè)并發(fā)安全的類型 sync.Map 來解決這個(gè)問題。

強(qiáng)類型下 Golang Array靈活性降低

接受它!

當(dāng)你接觸了 Golang 下數(shù)組們的實(shí)現(xiàn),會發(fā)現(xiàn)它真的沒有 php 下的數(shù)組靈活好用,這其實(shí)是強(qiáng)類型語言的通病,雖然 Golang 也可以通過定義 []interface{} 類型的 Slice,但是強(qiáng)烈不建議這樣用,強(qiáng)類型的優(yōu)點(diǎn)是讓我們盡可能早的發(fā)現(xiàn)問題,比如在編碼時(shí) IDE 就能做到提示,而非在運(yùn)行

到此這篇關(guān)于PHP轉(zhuǎn)Go之?dāng)?shù)組的正確使用詳解的文章就介紹到這了,更多相關(guān)PHP轉(zhuǎn)Go內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論