golang(2)

五, Array 與 slice

數組是固定長度的,slice是長度可以變的。但是slice是寄生在array上的。

數組的賦值爲有以下幾種寫法,但是無論那種,右邊的長度在編譯時都是已知的。左邊則是明確寫出,或者由編譯器自動識別;
var b[2]int=[2]int{11,12} //此時b是固定長度位2的數組。
var c[2]int=[...]int{11,12} //同上。
var d=[...]int{1,2,3,4}
e:=
[...]int{1,2,3,4}

slice是寄生於array的;其寫法爲:
var s=d[1:2],  //表示s是從第一個元素開始,第二個元素結束(不包括2)
var s1=d[:],    //表示s1是d的全部
var s2=d[:2],  //表示s2是0開始,2結束
var s3=d[1:], //表示從1開始到最後

一不小心突然發現有了一個新寫法
var a []int = [] int{1,2};以爲發現了一種新的數組賦值方法。這裏的a實際是slice;此時這個數組是匿名的了。

下面的代碼輸出位:
[1/2]0x7f71d56d5f4c &a=0x7f71d56d5f48 a=1 2 4 [1/1]0x7f71d56d5f54

點擊(此處)摺疊或打開

  1. var a = [...]int32{1, 2, 4}
  2.     var b = a[1:2]
  3.     print(b)
  4.     b = []int32{10}
  5.     print("&a=", &a, " a=")
  6.     for i := 0; i < len(a); i++ {
  7.         print(a[i], "\t")
  8.     }
  9.     print(b)
  10.     println()

  1. 可以見到在4行賦值前後,prinf出來的b的值變了,這是因爲此處打印的實際是該slice對應的數組的起始位置;
  2. 如果代碼中多出打印&b的值,就會發現&b是不會變化的;
  3. 實際在golang中(通過gdb彙編代碼可以看到),golang中的數組對應於實際c中的數組,指示預留空間比代碼中要求的要大;可以在gdb中用sizeof(a)看到;golang可以判斷對數組的訪問是否越界,這是通過在每次訪問下標前添加彙編代碼判斷達到的。這也是爲什麼數組的定義必須明確寫出長度的原因;
  4. 與數組相比, slice則而外多了一個結構體,其中有三個域,分別爲:指向該slice實際存儲區域的指針,當前slice的長度(len),和當前slice的容量(cap);

六,len注意點:

len(string)返回的是該字符串所佔用的字節數,而不是字符的個數。 由於都是utf-8,中文字符的長度超過了2, 所以總結果是13;

點擊(此處)摺疊或打開

  1. package main
  2. func main() {
  3. var s="Hello, 世界"
  4.     println(len(s))
  5. }
對於s,用c語言來描述是一個結構體,其中包含了兩個元素(str (*uint8), len(int64));其中str指向了真正的字符串;len中記錄了字符串的長度;

所以,只有array的長度是直接由編譯器得到,而slice,和string的長度則是有變量記錄的;

七, 指針

在golang中是有指針的,這一點給程序員帶來了很大的方便,java沒有提供求地址的功能,很是不便;比如下面的modify函數,如果在java中如果需要得到一個新的string值,只能通過返回值返回了。如果此時又有需求返回一個其他的返回值,就沒有辦法了;

點擊(此處)摺疊或打開

  1. package main
  2. func modify(a * string){
  3.         *a="hi"
  4. }
  5. func mo(b string){
  6.         b="compy"
  7. }
  8. func main(){
  9.         var s string="hello"
  10.         println(s)
  11.         mo(s)
  12.         println(s)
  13.         modify(&s)
  14.         println(s)
  15. }
通過上面的程序可以發現,modify函數傳進去的是s的地址,所以等函數返回後,s所對應的字符串已經更改;而mo函數中的b由於是s的copy,所以雖然在函數中修改了b的值,但是等函數返回後,仍沒有效果, 但是有一點需要注意的是,b這個copy中,指示上面的str,len兩個變量拷貝了,而實際的字符串只有一份,所以節約了空間,提供了性能;

寫這段代碼的時候,發現一個細節問題,如果註釋掉行13; 在gdb中調試到第10行是,可以使用p s命令和whatis s命令查看s的具體結構,但是如果留有13行,則symble table中的變量變成了&s,在gdb中可以使用i locals查看到該變量,但是如果用p打印該變量,還有待研究。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章