五, 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
點擊(此處)摺疊或打開
- var a =
[...]int32{1, 2,
4}
- var b = a[1:2]
- print(b)
- b = []int32{10}
- print("&a=",
&a,
" a=")
- for i := 0; i
< len(a); i++
{
- print(a[i],
"\t")
- }
- print(b)
- println()
- 可以見到在4行賦值前後,prinf出來的b的值變了,這是因爲此處打印的實際是該slice對應的數組的起始位置;
- 如果代碼中多出打印&b的值,就會發現&b是不會變化的;
- 實際在golang中(通過gdb彙編代碼可以看到),golang中的數組對應於實際c中的數組,指示預留空間比代碼中要求的要大;可以在gdb中用sizeof(a)看到;golang可以判斷對數組的訪問是否越界,這是通過在每次訪問下標前添加彙編代碼判斷達到的。這也是爲什麼數組的定義必須明確寫出長度的原因;
- 與數組相比, slice則而外多了一個結構體,其中有三個域,分別爲:指向該slice實際存儲區域的指針,當前slice的長度(len),和當前slice的容量(cap);
六,len注意點:
len(string)返回的是該字符串所佔用的字節數,而不是字符的個數。 由於都是utf-8,中文字符的長度超過了2, 所以總結果是13;
點擊(此處)摺疊或打開
- package main
- func main()
{
- var s="Hello, 世界"
- println(len(s))
- }
所以,只有array的長度是直接由編譯器得到,而slice,和string的長度則是有變量記錄的;
七, 指針
在golang中是有指針的,這一點給程序員帶來了很大的方便,java沒有提供求地址的功能,很是不便;比如下面的modify函數,如果在java中如果需要得到一個新的string值,只能通過返回值返回了。如果此時又有需求返回一個其他的返回值,就沒有辦法了;點擊(此處)摺疊或打開
- package main
- func modify(a
* string){
- *a="hi"
- }
- func mo(b string){
- b="compy"
- }
- func main(){
- var s string="hello"
- println(s)
- mo(s)
- println(s)
- modify(&s)
- println(s)
- }
寫這段代碼的時候,發現一個細節問題,如果註釋掉行13; 在gdb中調試到第10行是,可以使用p s命令和whatis s命令查看s的具體結構,但是如果留有13行,則symble table中的變量變成了&s,在gdb中可以使用i locals查看到該變量,但是如果用p打印該變量,還有待研究。