Go語言 基本類型

2020-06-01 10:57 更新

向新手介紹Go語言時,解釋一下Go中各種類型變量在內(nèi)存中的布局通常有利于幫助他們加深理解。

先看一些基礎(chǔ)的例子:

godata1

變量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ù)組。

結(jié)構(gòu)體和指針

與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ù)程序中都避免了這么做。)

links


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號