W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
向新手介紹Go語言時,解釋一下Go中各種類型變量在內(nèi)存中的布局通常有利于幫助他們加深理解。
先看一些基礎(chǔ)的例子:
變量i屬于類型int,在內(nèi)存中用一個32位字長(word)表示。(32位內(nèi)存布局方式)
變量j由于做了精確的轉(zhuǎn)換,屬于int32類型。盡管i和j有著相同的內(nèi)存布局,但是它們屬于不同的類型:賦值操作 i = j
是一種類型錯誤,必須寫成更精確的轉(zhuǎn)換方式:i = int(j)
。
變量f屬于float類型,Go語言當前使用32位浮點型值表示(float32)。它與int32很像,但是內(nèi)部實現(xiàn)不同。
接下來,變量bytes的類型是[5]byte,一個由5個字節(jié)組成的數(shù)組。它的內(nèi)存表示就是連起來的5個字節(jié),就像C的數(shù)組。類似地,變量primes是4個int的數(shù)組。
與C相同而與Java不同的是,Go語言讓程序員決定何時使用指針。舉例來說,這種類型定義:
type Point struct { X, Y int }
先來定義一個簡單的struct類型,名為Point,表示內(nèi)存中兩個相鄰的整數(shù)。
Point{10,20}
表示一個已初始化的Point類型。對它進行取地址表示一個指向剛剛分配和初始化的Point類型的指針。前者在內(nèi)存中是兩個詞,而后者是一個指向兩個詞的指針。
結(jié)構(gòu)體的域在內(nèi)存中是緊挨著排列的。
type Rect1 struct { Min, Max Point }
type Rect2 struct { Min, Max *Point }
Rect1是一個具有兩個Point類型屬性的結(jié)構(gòu)體,由在一行的兩個Point--四個int代表。Rect2是一個具有兩個*Point
類型屬性的結(jié)構(gòu)體,由兩個*Point表示。
使用過C的程序員可能對Point
和*Point
的不同毫不見怪,但用慣Java或Python的程序員們可能就不那么輕松了。Go語言給了程序員基本內(nèi)存層面的控制,由此提供了諸多能力,如控制給定數(shù)據(jù)結(jié)構(gòu)集合的總大小、內(nèi)存分配的次數(shù)、內(nèi)存訪問模式以及建立優(yōu)秀系統(tǒng)的所有要點。
有了前面的準備,我們就可以開始研究更有趣的數(shù)據(jù)類型了。
(灰色的箭頭表示已經(jīng)實現(xiàn)的但不能直接可見的指針)
字符串在Go語言內(nèi)存模型中用一個2字長的數(shù)據(jù)結(jié)構(gòu)表示。它包含一個指向字符串存儲數(shù)據(jù)的指針和一個長度數(shù)據(jù)。因為string類型是不可變的,對于多字符串共享同一個存儲數(shù)據(jù)是安全的。切分操作str[i:j]
會得到一個新的2字長結(jié)構(gòu),一個可能不同的但仍指向同一個字節(jié)序列(即上文說的存儲數(shù)據(jù))的指針和長度數(shù)據(jù)。這意味著字符串切分可以在不涉及內(nèi)存分配或復制操作。這使得字符串切分的效率等同于傳遞下標。
(說句題外話,在Java和其他語言里有一個有名的“疑難雜癥”:在你分割字符串并保存時,對于源字符串的引用在內(nèi)存中仍然保存著完整的原始字符串--即使只有一小部分仍被需要,Go也有這個“毛病”。另一方面,我們努力但又失敗了的是,讓字符串分割操作變得昂貴--包含一次分配和一次復制。在大多數(shù)程序中都避免了這么做。)
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: