Go編程語言中的指針是一個變量,用于存儲另一個變量的內(nèi)存地址。Golang中的指針也稱為特殊變量。變量被用于一些數(shù)據(jù)在系統(tǒng)中的一個特定存儲器地址存儲。始終以十六進(jìn)制格式找到內(nèi)存地址(以0x開頭,如0xFFAAF等)。
指針的作用?
要了解這種指針,首先,我們必須了解變量的概念。變量是賦予實際數(shù)據(jù)存儲位置的名稱。要訪問存儲的數(shù)據(jù),我們需要該特定存儲位置的地址。手動記住所有內(nèi)存地址(十六進(jìn)制格式)是一項開銷,這就是為什么我們使用變量來存儲數(shù)據(jù)并且僅通過使用變量名就可以訪問變量的原因。
Golang還允許使用文字表達(dá)式將十六進(jìn)制數(shù)保存到變量中,即,從0x開始的數(shù)字是十六進(jìn)制數(shù)。
示例:在下面的程序中,我們將十六進(jìn)制數(shù)存儲到變量中。但是您可以看到值的類型為int并保存為十進(jìn)制,或者可以說int類型的十進(jìn)制值正在存儲。但是,解釋此示例的主要要點是我們存儲的是十六進(jìn)制值(將其視為內(nèi)存地址),但它不是指針,因為它未指向另一個變量的任何其他內(nèi)存位置。它只是一個用戶定義的變量。因此,這就需要使用指針。
//存儲十六進(jìn)制值 package main import "fmt" func main() { //存儲十六進(jìn)制 //變量中的值 x := 0xFF y := 0x9C // 顯示值 fmt.Printf("變量x的類型為 %T\n", x) fmt.Printf("x的十六進(jìn)制值為 %X\n", x) fmt.Printf("x的十進(jìn)制值是 %v\n", x) fmt.Printf("變量y的類型為 %T\n", y) fmt.Printf("y的十六進(jìn)制值為 %X\n", y) fmt.Printf("y的十進(jìn)制值是 %v\n", y) }
輸出:
變量x的類型為 int x的十六進(jìn)制值為 FF x的十進(jìn)制值是 255 變量y的類型為 int y的十六進(jìn)制值為 9C y的十進(jìn)制值是 156
指針是一種特殊的變量,它不僅用于存儲其他變量的內(nèi)存地址,而且還指向內(nèi)存的位置,并提供查找存儲在該內(nèi)存位置的值的方法。它通常被稱為特殊類型的變量,因為它幾乎被聲明為變量,但是帶有*(解引用運(yùn)算符)。
在開始之前,我們將在指針中使用兩個重要的運(yùn)算符,即
*運(yùn)算符 也稱為解引用運(yùn)算符,用于聲明指針變量并訪問存儲在地址中的值。
&運(yùn)算符 稱為地址運(yùn)算符,用于返回變量的地址或?qū)⒆兞康牡刂吩L問指針。
聲明一個指針:
var pointer_name *Data_Type
示例:下面是字符串類型的指針,該指針只能存儲字符串變量的內(nèi)存地址。
var s *string
指針的初始化:為此,您需要使用地址運(yùn)算符使用另一個變量的內(nèi)存地址初始化指針,如以下示例所示:
//正常的變量聲明 var a = 45 //用初始化指針s //變量a的內(nèi)存地址 var s *int = &a
// Golang程序來演示聲明 //和指針的初始化 package main import "fmt" func main() { //定義一個正常變量 var x int = 5748 //指針聲明 var p *int //初始化指針 p = &x //顯示結(jié)果 fmt.Println("存儲在x中的值 = ", x) fmt.Println("x的內(nèi)存地址 = ", &x) fmt.Println("存儲在變量p中的值 = ", p) }
輸出:
存儲在x中的值 = 5748 x的內(nèi)存地址 = 0xc000066090 存儲在變量p中的值 = 0xc000066090
重要事項:
指針的默認(rèn)值或零值始終為nil。 或者,您可以說未初始化的指針將始終具有nil值。
//指針的nil值 package main import "fmt" func main() { //定義指針 var s *int // 顯示結(jié)果 fmt.Println("s = ", s) }
輸出:
s = <nil>
指針的聲明和初始化可以在一行中完成。
var s *int = &a
如果要同時指定數(shù)據(jù)類型和指針聲明,則指針將能夠處理該指定數(shù)據(jù)類型變量的內(nèi)存地址。例如,如果您使用字符串類型的指針,那么將提供給指針的變量的地址將僅是字符串?dāng)?shù)據(jù)類型變量,而不是其他任何類型。
為了克服上述問題,可以使用var關(guān)鍵字的類型推斷概念。聲明期間無需指定的數(shù)據(jù)類型。指針變量的類型也可以像普通變量一樣由編譯器確定。在這里,我們將不使用*運(yùn)算符。當(dāng)我們使用另一個變量的地址初始化變量時,它將由編譯器內(nèi)部確定。
// Golang程序進(jìn)行演示 //在中使用類型推斷 //指針變量 package main import "fmt" func main() { //使用var關(guān)鍵字 //我們沒有定義 //任何帶變量的類型 var y = 458 //使用指針變量 // var關(guān)鍵字,不指定 //類型 var p = &y fmt.Println("存儲在y中的值 = ", y) fmt.Println("y的地址= ", &y) fmt.Println("存儲在指針變量p中的值 = ", p) }
輸出:
存儲在y中的值 = 458 y的地址= 0xc0000120a8 存儲在指針變量p中的值 = 0xc0000120a8
您也可以使用簡寫(:=)語法來聲明和初始化指針變量。如果我們使用&(address)運(yùn)算符將變量的地址傳遞給它,則編譯器將在內(nèi)部確定該變量為指針變量。
// Golang程序進(jìn)行演示 //在中使用速記語法 //指針變量 package main import "fmt" func main() { //使用:=運(yùn)算符進(jìn)行聲明 //并初始化變量 y := 458 //使用一個指針變量 //通過:=為其分配 //變量y的地址 p := &y fmt.Println("存儲在y中的值 = ", y) fmt.Println("y的地址= ", &y) fmt.Println("存儲在指針變量p中的值 = ", p) }
輸出:
存儲在y中的值 = 458 y的地址= 0xc000066090 存儲在指針變量p中的值 = 0xc000066090
眾所周知,*運(yùn)算符也稱為解引用運(yùn)算符。它不僅用于聲明指針變量,而且還用于訪問指針?biāo)赶虻淖兞恐写鎯Φ闹?,通常將其稱為間接或取消引用。*運(yùn)算符也稱為地址處的值。讓我們舉個實例來更好地理解這個概念:
// Golang程序舉例說明 //解除指針引用的概念 package main import "fmt" func main() { //使用var關(guān)鍵字 //我們沒有定義 //任何帶變量的類型 var y = 458 //使用指針變量 // var關(guān)鍵字,不指定 //類型 var p = &y fmt.Println("存儲在y中的值 = ", y) fmt.Println("y的地址= ", &y) fmt.Println("存儲在指針變量p中的值 = ", p) //這是取消引用指針 //在指針之前使用*運(yùn)算符 //變量以訪問存儲的值 //指向它所指向的變量 fmt.Println("存儲在y中的值(*p) = ", *p) }
輸出:
存儲在y中的值 = 458 y的地址= 0xc0000120a8 存儲在指針變量p中的值 = 0xc0000120a8 存儲在y中的值(*p) = 458
您也可以更改指針的值或在內(nèi)存的位置,而不是為變量分配新值。
package main import "fmt" func main() { //使用var關(guān)鍵字 //我們沒有定義 //沒有指定變量的類型 var y = 458 //使用指針變量 // var關(guān)鍵字,不指定類型 var p = &y fmt.Println("更改前存儲在y中的值 = ", y) fmt.Println("y的地址 = ", &y) fmt.Println("存儲在指針變量p中的值 = ", p) //這是取消引用指針 //在指針之前使用*運(yùn)算符 //變量以訪問存儲的值 //指向它所指向的變量 fmt.Println("更改前存儲在y(*p)中的值 = ", *p) //通過賦值改變y的值 //指針的新值 *p = 500 fmt.Println("更改后存儲在y(*p)中的值 = ", y) }
輸出:
更改前存儲在y中的值 = 458 y的地址 = 0xc0000120a8 存儲在指針變量p中的值 = 0xc0000120a8 更改前存儲在y(*p)中的值 = 458 更改后存儲在y(*p)中的值 = 500