Go初識-day3-變量、值類型與引用類型

變量

格式

var 變量名 類型
變量名 := 值 //[1]

[1] 第一次聲明可使用:=,Go會自動做類型推導

  • 在Golang中變量名是寫在前面,類型則是寫在後面

example

範例 1

1
2
3
4
5
var a int
var b string
var c bool
var d int = 8 //[1]
var e string = "Hello world" //[1]

[1] 聲明變量並初始化為=右邊之值若無指定初始化之值
int默認為0,string默認為空字符串,bool默認為false

範例 2 (多變量一起聲明)

1
2
3
4
5
6
7
var (
a int
b string
c bool
d int = 8
e string = "Hello world"
)

範例 3

1
2
3
4
5
6
7
var (
a int
b string
c bool
d = 8 //[1]
e = "Hello world" //[1]
)

[1] 在聲明變量時可不附類型,go會自己做類型推斷

範例 4

1
2
3
4
5
a := 0
b := ""
c := false
d := 8
e := "Hello world"

值類型和引用類型

值類型

變量中直接存儲值

value_type

  • a 被分配了一個內存空間,a直接指向這個內存空間,這個空間存放的值為5
  • 內存通常在中分配
  • 基本數據類型int,float,bool,string以及arraystruct都是值類型

引用類型

變量中存儲的是一個地址,這個地址指向的才是值

ref type

  • 在函數中使用引用類型的值作為參數效率較高(傳入參數為複製地址,而非複製值)
  • 內存通常在上分配,通過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
30
package 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
2
3
4
Before: 1
After: 1
SendValue: 1
PickValue: 100
  • 從執行結果可以發現,值類型的參數傳遞到函數中時,是複製了一份一模一樣的值傳入,函數中修改的是複製的值,而非原本的值,所以函數外部的值不管有沒有經過函數都沒有變化
  • 引用類型在函數中傳參時,操作的就是同一塊內存空間,所以經過函數時,channel的值發生了改變

practice 2

寫一個程序,交換兩個整數值比如a=3;b=4,交換之後a=4;b=3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package 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