引言
當你用Go編寫軟件時,你將編寫函數和方法。你可以將數據作為參數傳遞給這些函數。有時,函數需要數據的本地副本,而你希望原始數據保持不變。例如,如果你是一家銀行,你有一個函數向用戶顯示根據他們選擇的儲蓄計劃而產生的余額變化,你不希望在客戶選擇計劃之前更改他們的實際余額;你只是想在計算中使用它。這被稱為按值傳遞,因為你將變量的值發送給函數,而不是變量本身。
其他時候,你可能希望函數能夠改變原始變量中的數據。例如,當銀行客戶向他們的賬戶存款時,您希望存款功能能夠訪問實際余額,而不是副本。在這種情況下,你不需要將實際數據發送給函數;你只需要告訴函數數據在內存中的位置。一種稱為指針的數據類型保存的是數據的內存地址,而不是數據本身。內存地址告訴函數在哪里找到數據,而不是數據的值。你可以將指針而不是數據傳遞給函數,然后函數可以原地改變原始變量。這被稱為引用傳遞,因為變量的值并沒有傳遞給函數,只有它的位置。
在本文中,您將創建和使用指針來共享對變量內存空間的訪問。
定義和使用指針
當你使用指向變量的指針時,有幾個不同的語法元素需要你理解。第一個是和號(&
)的使用。如果你在變量名前放一個&符號,你是在聲明你想要獲取地址,或者指向該變量的指針。第二個語法元素是使用星號(*
)或解引用操作符。當你聲明一個指針變量時,在變量名后面加上指針所指向的變量的類型,并以*
作為前綴,像這樣:
var myPointer *int32 = &someint
這將創建myPointer
作為一個指向int32
變量的指針,并將指針初始化為someint
的地址。這個指針實際上并沒有包含int32
,只是一個int32
的地址。
讓我們看一下指向string
的指針。下面的代碼聲明了一個字符串的值和一個指向字符串的指針:
main.go
package mainimport "fmt"func main() {var creature string = "shark"var pointer *string = &creaturefmt.Println("creature =", creature)fmt.Println("pointer =", pointer)
}
使用下面的命令運行這個程序:
go run main.go
運行這個程序時,它會打印出變量的值,以及變量的存儲地址(指針地址)。內存地址是十六進制數,并不是人類可讀的。在實踐中,您可能永遠不會輸出內存地址來查看它。我們展示給你們是為了說明。因為每個程序在運行時都是在自己的內存空間中創建的,所以每次運行時指針的值都不一樣,也和下面的輸出不一樣:
Outputcreature = shark
pointer = 0xc0000721e0
我們定義的第一個變量名為creature
,并將它設置為一個值為shark
的string
。然后我們創建了另一個名為pointer
的變量。這次,我們將pointer
變量的值設置為creature
變量的地址。我們使用&符號(’ & ')將值的地址存儲在變量中。這意味著pointer
變量存儲的是creature
變量的地址,而不是實際值。
這就是為什么當我們打印pointer
的值時,我們收到了0xc0000721e0
的值,這是creature
變量當前存儲在計算機內存中的地址。
如果你想打印出pointer
變量指向的變量的值,你需要解引用該變量。下面的代碼使用*
操作符解引pointer
變量并獲取它的值:
main.go
package mainimport "fmt"func main() {var creature string = "shark"var pointer *string = &creaturefmt.Println("creature =", creature)fmt.Println("pointer =", pointer)fmt.Println("*pointer =", *pointer)
}
Outputcreature = shark
pointer = 0xc000010200
*pointer = shark
我們現在添加的最后一行解引了pointer
變量,并打印出存儲在該地址的值。
如果你想修改存儲在pointer
變量位置的值,你也可以使用解引用操作符:
main.go
package mainimport "fmt"func main() {var creature string = "shark"var pointer *string = &creaturefmt.Println("creature =", creature)fmt.Println("pointer =", pointer)fmt.Println("*pointer =", *pointer)*pointer = "jellyfish"fmt.