1. 程式人生 > >GoLang學習筆記(十六)指標

GoLang學習筆記(十六)指標

指標是儲存另一個變數的記憶體地址的變數。
變數是一種使用方便的佔位符,變數都只想計算機的記憶體地址。
一個指標變數可以指向任何一個值的記憶體地址
GoLang獲取一個變數的地址,在一個變數前使用&符號,會返回該變數的記憶體地址.
GoLang的指標是不能參與運算的。
宣告指標,*T是指標變數的型別,它指向T型別的值。
格式:var 指標變數名 *指標型別(如var ip *int)
在一個指標變數前加上一個*符號,則獲取該指標變數真實的值。

來一個例子,獲取變數地址:

func getVariableAddr() {
	a := 10
	fmt.Printf("變數的地址:%x \n", &a)
	arr := []int{1, 2, 3, 4, 5}
	fmt.Printf("變數的地址:%x \n", &arr)
}

執行後可獲得該變數的地址,接著申明指標變數的例子:

func declarePointer() {
	//定義一個實際變數
	a := 100
	//申明一個指標變數
	var ip *int
	//給指標變數賦值
	ip = &a
	//獲取指標變數的值
	fmt.Println(ip)
	//獲取指標變數記憶體地址的實際值
	fmt.Println(*ip)
}

宣告一個複合變數的指標:

先宣告一個複合型別:

type student struct {
	name    string
	age     int
	married bool
	sex     int8
}

接著來做複合變數的指標:

func complexType1() {
	s1 := student{"yoni", 37, true, 1}
	s2 := student{"oscar", 35, true, 0}

	var a *student = &s1
	var b *student = &s2

	fmt.Println("\n-------------")
	fmt.Printf("S1的型別為%T,值為%v \n", s1, s1)
	fmt.Printf("S2的型別為%T,值為%v \n", s2, s2)

	fmt.Println("\n-------------")
	fmt.Printf("a的型別為%T,值為%v \n", a, a)
	fmt.Printf("b的型別為%T,值為%v \n", b, b)

	fmt.Println("\n-------------")
	fmt.Printf("*a的型別為%T,值為%v \n", *a, *a)
	fmt.Printf("*b的型別為%T,值為%v \n", *b, *b)

	fmt.Println("\n-------------")
	fmt.Println(s1.name, s1.age, s1.married, s1.sex)
	fmt.Println(a.name, a.age, a.married, a.sex)

	fmt.Println("\n-------------")
	fmt.Println((*a).name, (*a).age, (*a).married, (*a).sex)
	fmt.Println(&a.name, &a.age, &a.married, &a.sex)
}

空指標的例子:

func nullPointer() {
	var pval *int
	fmt.Printf("pval指標的型別為%T,值為%v \n", pval, pval)
	if pval == nil {
		fmt.Println("prval為空指標")
	} else {
		fmt.Println("pval有指標")
	}
}

通過指標改變變數值的例子:

func pointer1() {
	a := 10
	var b *int = &a
	fmt.Printf("b的型別%T,數值%v \n", b, b)
	fmt.Println("a的地址", b)
	fmt.Println("*b的值", *b)
	*b++
	fmt.Println("a的值", a)
}

將指標作為函式引數:

func change1() {
	a := 10
	fmt.Println("呼叫函式前的A值", a)
	b := &a
	dochange1(b)
	fmt.Println("呼叫函式後的A值", a)
}

func dochange1(num *int) {
	*num = 50
}

將兩個值資料互換的例子:

func swap() {
    a,b := 100,200
    //傳統寫法
    a,b = doSwap1(a,b)
	fmt.Println("傳統交換後:",a,b)
    //指標寫法
    doSwap2(&a,&b)
    fmt.Println("指標交換後:",a,b)
}

func doSwap1(x, y int) (int, int) {
	return y, x
}

func doSwap2(x, y *int) {
	*x, *y = *y, *x
}

對切片進行指標操作:

func modify() {
    arr := []int {1,2,3,4,5}
    doModify(&arr)
    fmt.Println(arr)
}

func doModify(arr *[]int){
	(*arr)[0] = 500
}

對切片指標進行操作,雖然可以用指標來修改,但使用指標不是最好的辦法。

 

指標的指標:

func pointerPointer(){
	var a int
	var ptr *int
	var pptr **int

	a = 123
    //為指標賦值
	ptr = &a
	fmt.Println("ptr:",ptr)
    //為指標的指標賦值
	pptr = &ptr
	fmt.Println("pptr:",pptr)
}