2016-08-22 56 views
3

Go內置len() function返回一個簽名int。爲什麼不使用uint呢?爲什麼len()返回一個有符號的值?

len()有可能返回負面的東西嗎?
至於我可以告訴大家,答案是否定的:

  • Arrays:「元素的數量稱爲長度,從不爲負」
  • Slices:「在任何時候滿足下面的關係:0 <= len(s) <= cap(s)
  • Maps「地圖元素的數量被稱爲它的長度」。 (我在規範中找不到任何明確將其限制爲非負值的任何內容,但我很難理解地圖中可能少於0個元素的情況)
  • Strings「字符串值是(可能的空)字節序列....可以使用內置函數len()「(再次難以理解序列如何具有負數字節)發現字符串s的長度(其字節大小)
  • Channels「元素的數目通道緩衝器排隊(同上)
+1

如果要解決切片的第2147483648個元素,「uint」可能會更好。但是,如果你想解決第4294967296個問題,你會遇到麻煩。 –

回答

2

Length and capacity

內置函數len和cap使用各種類型的參數,並返回int類型的結果。該實現保證 結果始終適合int。

Golang是強類型語言,所以如果len()uint然後代替:

i := 0 // int 
if len(a) == i { 
} 

你應該寫:

if len(a) == uint(i) { 
} 

或:

if int(len(a)) == i { 
} 

另請參見:

uint是32位或64位
int大小相同uint
uintptran unsigned integer large enough to store the uninterpreted bits of a pointer value

兼與C兼容性:CGoC.size_t和用C陣列的大小是int類型。

+0

是否需要轉換?一個快速實驗表明,你可以將int和uint值與整數文字進行比較而不會有任何問題(儘管試圖比較int和uint變量會導致「不匹配類型」錯誤)。 –

+0

@KeithThompson for untyped numbers你是對的,這是虛構的例子,謝謝。 – 2016-08-22 22:06:26

2

the spec:

長度數組的類型的一部分;它必須評估爲一個可用int類型值表示的非負常數。使用內置函數len可以發現陣列a的長度。這些元素可以用整數索引0len(a)-1來尋址。數組類型始終是一維的,但可以組成多維類型。

我意識到這也許有點圓說該規範規定X因爲該規範規定Ÿ,但由於長度不能超過一個int的最大值,這是同樣的len是不可能的返回一個uint專有值,它會返回一個負值。

+0

(推測)我可以考慮一些語言作者希望數組被索引爲* signed *整數的好理由。數組通常被分配爲內存塊[需要的引用],並使用指針算法來處理元素[需要的引用]。您可以將元數據(如數組的長度)存儲在一個負偏移量[需要的引用]中,並且通過添加可能是或可能不是負數的偏移量來代表某些數組操作可能會非常容易,而不是有條件地添加或減去偏移。 –

2

len()(和cap())return int因爲這是用於索引切片和數組(而不是uint)。所以問題更多的是「爲什麼Go使用帶符號整數來索引切片/數組時沒有負指數?」。

答案很簡單:計算計算常見,如果以無符號整數完成,則這種計算往往會非常容易下溢。一些無辜的代碼,如i := a-b+7可能會產生i == 4294967291ab 6和10的無辜值。這樣的索引可能會溢出您的切片。大量的索引計算髮生在0左右,使用無符號整數很難得到正確的結果,這些錯誤隱藏在數學上完全合理和合理的公式中。這既不安全也不方便。

這是一個基於經驗的折衷:下溢往往會發生在使用無符號整數進行索引計算的情況下,而如果使用帶符號整數進行索引計算,則溢出很少出現。

此外:在這些情況下使用無符號整數基本上沒有任何好處。

+0

我認爲Go運行時會檢查對陣列或片的任何訪問類型,因此當我們討論_indexes_時,帶有signed或unsigned整數的下溢在其後果(運行時恐慌)中是完全相等的。但是,當使用它來計算要分配的數組的_length_或_capacity_時,無符號數學仍然會有問題。 –

+0

@RomanKhimov是的,**如果**發生過度/下溢,後果是相同的。我的觀點是:如果使用帶符號的整數,則流量更少...更多...流如果使用無符號整數進行索引計算,因爲0附近的索引比MaxUint32附近的索引要普遍得多。 – Volker

相關問題