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

PHP轉(zhuǎn)Go之?dāng)?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

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

使用中的注意事項及坑坑

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

一、思維速轉(zhuǎn)

PHP 中 Array 實在是太好用了,即可以聲明為索引數(shù)組,又可以聲明為關(guān)聯(lián)數(shù)組;但是在 Golang 中,被拆解成了多個數(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",   // 特別注意強類型下 map 中值部分無法存放不同類型的數(shù)據(jù)
}

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

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

Array 底層實現(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: 可以看到每個元素偏移剛好是 4 個字節(jié)
0xc0000a6030 0xc0000a6034 0xc0000a6038

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

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

Slice 底層實現(xiàn)

Slice 實際上底層也是引用了數(shù)組的實現(xiàn),但是它在數(shù)組的上面又封裝了一層數(shù)據(jù)結(jié)構(gòu),當(dāng)我們打印 Slice 中每個元素的內(nèi)存地址時你會發(fā)現(xiàn)其每個元素的偏移規(guī)則與數(shù)組是一致的。差別在于當(dāng)我們打印整個數(shù)組的指針地址時會發(fā)現(xiàn)其與數(shù)組第一個元素的地址是一致的,而 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 // 與第一個元素一致
&[1 2 3] 0xc000018120 0xc000018128 0xc000018130
slice : 0xc000010078 // 指向 Slice 結(jié)構(gòu)體指針,故與第一個元素內(nèi)存不一致
&[1 2 3] 0xc000018150 0xc000018158 0xc000018160

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

Map 底層實現(xiàn)

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

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

使用中的注意事項及坑坑

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 時要特別注意這一項,是否擔(dān)心子函數(shù)意外修改數(shù)據(jù)

Map 的無序的坑

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

并發(fā)安全性

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

強類型下 Golang Array靈活性降低

接受它!

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

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

相關(guān)文章

  • 探討各種PHP字符串函數(shù)的總結(jié)分析

    探討各種PHP字符串函數(shù)的總結(jié)分析

    本篇文章是對各種PHP字符串函數(shù)進(jìn)行了詳細(xì)的總結(jié)與分析,需要的朋友參考下
    2013-06-06
  • PHP生成和獲取XML格式數(shù)據(jù)的方法

    PHP生成和獲取XML格式數(shù)據(jù)的方法

    這篇文章主要介紹了PHP生成和獲取XML格式數(shù)據(jù)的方法,結(jié)合實例形式較為詳細(xì)的分析了PHP操作數(shù)據(jù)庫生成XML及獲取XML格式數(shù)據(jù)的相關(guān)技巧,需要的朋友可以參考下
    2016-03-03
  • php 批量替換html標(biāo)簽的實例代碼

    php 批量替換html標(biāo)簽的實例代碼

    這篇文章主要是對php批量替換html標(biāo)簽的實例代碼進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-11-11
  • PHP浮點數(shù)精度問題匯總

    PHP浮點數(shù)精度問題匯總

    這篇文章主要介紹了PHP浮點數(shù)精度問題匯總,本文著重探討PHP浮點數(shù)精度損失問題,用三個段落不同的方式講解了這個問題的形成原因以及解決方法,需要的朋友可以參考下
    2015-05-05
  • PHP 99乘法表的幾種實現(xiàn)代碼

    PHP 99乘法表的幾種實現(xiàn)代碼

    對于剛學(xué)PHP的新手來講,用php寫九九乘法表無疑是非常經(jīng)典的一道練習(xí)題,但不要小看這道練習(xí)題,它對于邏輯的考驗還是相當(dāng)?shù)轿坏?,這里腳本之家小編就為大家分享一下
    2020-10-10
  • PHP獲取二叉樹鏡像的方法

    PHP獲取二叉樹鏡像的方法

    這篇文章主要介紹了PHP獲取二叉樹鏡像的方法,涉及php使用隊列針對二叉樹進(jìn)行翻轉(zhuǎn)的相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • php 利用socket發(fā)送HTTP請求(GET,POST)

    php 利用socket發(fā)送HTTP請求(GET,POST)

    作為php程序員一定會接觸http協(xié)議,也只有深入了解http協(xié)議,編程水平才會更進(jìn)一步。最近我一直在學(xué)習(xí)php的關(guān)于http的編程,許多東西恍然大悟,受益匪淺。希望分享給大家。本文需要有一定http基礎(chǔ)的開發(fā)者閱讀。
    2015-08-08
  • php實現(xiàn)購物車功能(以大蘋果購物網(wǎng)為例)

    php實現(xiàn)購物車功能(以大蘋果購物網(wǎng)為例)

    本文主要介紹了php實現(xiàn)購物車功能(以大蘋果購物網(wǎng)為例)的實現(xiàn)方法,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • php獲取通過http協(xié)議post提交過來xml數(shù)據(jù)及解析xml

    php獲取通過http協(xié)議post提交過來xml數(shù)據(jù)及解析xml

    php 如何獲取請求的xml數(shù)據(jù),對方通過http協(xié)議post提交過來xml數(shù)據(jù),php如何獲取到這些數(shù)據(jù)呢?
    2012-12-12
  • PHP基于單例模式實現(xiàn)的數(shù)據(jù)庫操作基類

    PHP基于單例模式實現(xiàn)的數(shù)據(jù)庫操作基類

    這篇文章主要介紹了PHP基于單例模式實現(xiàn)的數(shù)據(jù)庫操作基類,涉及PHP操作數(shù)據(jù)庫的基本配置與增刪改查等操作技巧,需要的朋友可以參考下
    2016-01-01

最新評論