Go 语言指针
Go编程语言中的指针是一个变量,用于存储另一个变量的内存地址。Golang中的指针也称为特殊变量。变量被用于一些数据在系统中的一个特定存储器地址存储。始终以十六进制格式找到内存地址(以0x开头,如0xFFAAF等)。
指针的作用?
要了解这种指针,首先,我们必须了解变量的概念。变量是赋予实际数据存储位置的名称。要访问存储的数据,我们需要该特定存储位置的地址。手动记住所有内存地址(十六进制格式)是一项开销,这就是为什么我们使用变量来存储数据并且仅通过使用变量名就可以访问变量的原因。
Golang还允许使用文字表达式将十六进制数保存到变量中,即,从0x开始的数字是十六进制数。
示例:在下面的程序中,我们将十六进制数存储到变量中。但是您可以看到值的类型为int并保存为十进制,或者可以说int类型的十进制值正在存储。但是,解释此示例的主要要点是我们存储的是十六进制值(将其视为内存地址),但它不是指针,因为它未指向另一个变量的任何其他内存位置。它只是一个用户定义的变量。因此,这就需要使用指针。
//存储十六进制值 package main import "fmt" func main() { //存储十六进制 //变量中的值 x := 0xFF y := 0x9C // 显示值 fmt.Printf("变量x的类型为 %T\n", x) fmt.Printf("x的十六进制值为 %X\n", x) fmt.Printf("x的十进制值是 %v\n", x) fmt.Printf("变量y的类型为 %T\n", y) fmt.Printf("y的十六进制值为 %X\n", y) fmt.Printf("y的十进制值是 %v\n", y) }
输出:
变量x的类型为 int x的十六进制值为 FF x的十进制值是 255 变量y的类型为 int y的十六进制值为 9C y的十进制值是 156
指针是一种特殊的变量,它不仅用于存储其他变量的内存地址,而且还指向内存的位置,并提供查找存储在该内存位置的值的方法。它通常被称为特殊类型的变量,因为它几乎被声明为变量,但是带有*(解引用运算符)。
指针的声明和初始化
在开始之前,我们将在指针中使用两个重要的运算符,即
*运算符 也称为解引用运算符,用于声明指针变量并访问存储在地址中的值。
&运算符 称为地址运算符,用于返回变量的地址或将变量的地址访问指针。
声明一个指针:
var pointer_name *Data_Type
示例:下面是字符串类型的指针,该指针只能存储字符串变量的内存地址。
var s *string
指针的初始化:为此,您需要使用地址运算符使用另一个变量的内存地址初始化指针,如以下示例所示:
//正常的变量声明 var a = 45 //用初始化指针s //变量a的内存地址 var s *int = &a
// Golang程序来演示声明 //和指针的初始化 package main import "fmt" func main() { //定义一个正常变量 var x int = 5748 //指针声明 var p *int //初始化指针 p = &x //显示结果 fmt.Println("存储在x中的值 = ", x) fmt.Println("x的内存地址 = ", &x) fmt.Println("存储在变量p中的值 = ", p) }
输出:
存储在x中的值 = 5748 x的内存地址 = 0xc000066090 存储在变量p中的值 = 0xc000066090
重要事项:
指针的默认值或零值始终为nil。 或者,您可以说未初始化的指针将始终具有nil值。
//指针的nil值 package main import "fmt" func main() { //定义指针 var s *int // 显示结果 fmt.Println("s = ", s) }
输出:
s = <nil>
指针的声明和初始化可以在一行中完成。
var s *int = &a
如果要同时指定数据类型和指针声明,则指针将能够处理该指定数据类型变量的内存地址。例如,如果您使用字符串类型的指针,那么将提供给指针的变量的地址将仅是字符串数据类型变量,而不是其他任何类型。
为了克服上述问题,可以使用var关键字的类型推断概念。声明期间无需指定的数据类型。指针变量的类型也可以像普通变量一样由编译器确定。在这里,我们将不使用*运算符。当我们使用另一个变量的地址初始化变量时,它将由编译器内部确定。
// Golang程序进行演示 //在中使用类型推断 //指针变量 package main import "fmt" func main() { //使用var关键字 //我们没有定义 //任何带变量的类型 var y = 458 //使用指针变量 // var关键字,不指定 //类型 var p = &y fmt.Println("存储在y中的值 = ", y) fmt.Println("y的地址= ", &y) fmt.Println("存储在指针变量p中的值 = ", p) }
输出:
存储在y中的值 = 458 y的地址= 0xc0000120a8 存储在指针变量p中的值 = 0xc0000120a8
您也可以使用简写(:=)语法来声明和初始化指针变量。如果我们使用&(address)运算符将变量的地址传递给它,则编译器将在内部确定该变量为指针变量。
// Golang程序进行演示 //在中使用速记语法 //指针变量 package main import "fmt" func main() { //使用:=运算符进行声明 //并初始化变量 y := 458 //使用一个指针变量 //通过:=为其分配 //变量y的地址 p := &y fmt.Println("存储在y中的值 = ", y) fmt.Println("y的地址= ", &y) fmt.Println("存储在指针变量p中的值 = ", p) }
输出:
存储在y中的值 = 458 y的地址= 0xc000066090 存储在指针变量p中的值 = 0xc000066090
指针解引用
众所周知,*运算符也称为解引用运算符。它不仅用于声明指针变量,而且还用于访问指针所指向的变量中存储的值,通常将其称为间接或取消引用。*运算符也称为地址处的值。让我们举个实例来更好地理解这个概念:
// Golang程序举例说明 //解除指针引用的概念 package main import "fmt" func main() { //使用var关键字 //我们没有定义 //任何带变量的类型 var y = 458 //使用指针变量 // var关键字,不指定 //类型 var p = &y fmt.Println("存储在y中的值 = ", y) fmt.Println("y的地址= ", &y) fmt.Println("存储在指针变量p中的值 = ", p) //这是取消引用指针 //在指针之前使用*运算符 //变量以访问存储的值 //指向它所指向的变量 fmt.Println("存储在y中的值(*p) = ", *p) }
输出:
存储在y中的值 = 458 y的地址= 0xc0000120a8 存储在指针变量p中的值 = 0xc0000120a8 存储在y中的值(*p) = 458
您也可以更改指针的值或在内存的位置,而不是为变量分配新值。
package main import "fmt" func main() { //使用var关键字 //我们没有定义 //没有指定变量的类型 var y = 458 //使用指针变量 // var关键字,不指定类型 var p = &y fmt.Println("更改前存储在y中的值 = ", y) fmt.Println("y的地址 = ", &y) fmt.Println("存储在指针变量p中的值 = ", p) //这是取消引用指针 //在指针之前使用*运算符 //变量以访问存储的值 //指向它所指向的变量 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