變量
格式
var 變量名 類型
變量名 := 值 //[1]
[1] 第一次聲明可使用:=
,Go會自動做類型推導
- 在Golang中變量名是寫在前面,類型則是寫在後面
example
範例 1
1 | var a int |
[1] 聲明變量並初始化為=
右邊之值若無指定初始化之值int
默認為0,string
默認為空字符串,bool
默認為false
範例 2 (多變量一起聲明)
1 | var ( |
範例 3
1 | var ( |
[1] 在聲明變量時可不附類型,go會自己做類型推斷
範例 4
1 | a := 0 |
值類型和引用類型
值類型
變量中直接存儲值
- a 被分配了一個內存空間,a直接指向這個內存空間,這個空間存放的值為5
- 內存通常在棧中分配
- 基本數據類型
int
,float
,bool
,string
以及array
和struct
都是值類型
引用類型
變量中存儲的是一個地址,這個地址指向的才是值
- 在函數中使用引用類型的值作為參數效率較高(傳入參數為複製地址,而非複製值)
- 內存通常在堆上分配,通過GC回收
- 指針(pointer)、切片(
slice
),map
,chan
皆為引用類型
practice 1
寫一個程序用來展示值類型和引用類型到終端,並觀察輸出結果1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package main
import "fmt"
func ModifyValue(a int){
a = 100
return
}
func ModifyRef(a chan int){
b := <- a
b = 100
a <- b
return
}
func main(){
Value := 1
fmt.Println("Before:",Value)
ModifyValue(Value)
fmt.Println("After:",Value)
BeforeChannel := make(chan int,1)
SendValue := 1
BeforeChannel <- SendValue
ModifyRef(BeforeChannel)
PickValue := <- BeforeChannel
fmt.Println("SendValue:",SendValue)
fmt.Println("PickValue:",PickValue)
}
result
1 | Before: 1 |
- 從執行結果可以發現,值類型的參數傳遞到函數中時,是複製了一份一模一樣的值傳入,函數中修改的是複製的值,而非原本的值,所以函數外部的值不管有沒有經過函數都沒有變化
- 引用類型在函數中傳參時,操作的就是同一塊內存空間,所以經過函數時,channel的值發生了改變
practice 2
寫一個程序,交換兩個整數值比如a=3;b=4,交換之後a=4;b=31
2
3
4
5
6
7
8
9
10
11
12
13
14
15package main
import "fmt"
func change(a,b *int){ //[1]
*a,*b = *b,*a //[2]
return
}
func main(){
a := 3
b := 4
change(&a,&b) //[3]
fmt.Println("a=",a,"b=",b)
}
[1] change函數接收的為int類型的指針
[2] 參數為指針類型,使用*
則是向內存地址指向的內存空間取值
[3] 因change函數接受為指針類型的參數,&取址符為對後面的變量取得其內存地址
result
1 | a= 4 b= 3 |