📜  Golang 中的指针

📅  最后修改于: 2021-10-24 13:08:55             🧑  作者: Mango

Go 编程语言或 Golang 中的指针是一个变量,用于存储另一个变量的内存地址。 Golang 中的指针也称为特殊变量。这些变量用于在系统中的特定内存地址存储一些数据。内存地址总是以十六进制格式(以 0x 开头,如 0xFFAAF 等)。

需要什么指针?

要理解这种需求,首先,我们必须了解变量的概念。变量是存储实际数据的内存位置的名称。要访问存储的数据,我们需要该特定内存位置的地址。手动记住所有内存地址(十六进制格式)是一种开销,这就是为什么我们使用变量来存储数据并且变量可以通过使用它们的名称来访问。
Golang 还允许使用字面量表达式将十六进制数保存到变量中,即从0x开始的数字是十六进制数。

示例:在下面的程序中,我们将十六进制数存储到一个变量中。但是你可以看到值的类型是int并保存为十进制或者你可以说int类型的十进制值正在存储。但是解释这个例子的要点是我们正在存储一个十六进制值(将其视为一个内存地址)但它不是一个指针,因为它没有指向另一个变量的任何其他内存位置。它只是一个用户定义的变量。所以这就产生了对指针的需求。

Go
// Golang program to demonstrate the variables
// storing the hexadecimal values
package main
 
import "fmt"
 
func main() {
 
    // storing the hexadecimal
    // values in variables
    x := 0xFF
    y := 0x9C
     
    // Displaying the values
    fmt.Printf("Type of variable x is %T\n", x)
    fmt.Printf("Value of x in hexadecimal is %X\n", x)
    fmt.Printf("Value of x in decimal is %v\n", x)
     
    fmt.Printf("Type of variable y is %T\n", y)
    fmt.Printf("Value of y in hexadecimal is %X\n", y)
    fmt.Printf("Value of y in decimal is %v\n", y)   
     
}


Go
// Golang program to demonstrate the declaration
// and initialization of pointers
package main
 
import "fmt"
 
func main() {
 
    // taking a normal variable
    var x int = 5748
     
    // declaration of pointer
    var p *int
     
    // initialization of pointer
    p = &x
 
        // displaying the result
    fmt.Println("Value stored in x = ", x)
    fmt.Println("Address of x = ", &x)
    fmt.Println("Value stored in variable p = ", p)
}


Go
// Golang program to demonstrate
// the nil value of the pointer
package main
 
import "fmt"
 
func main() {
 
        // taking a pointer
    var s *int
     
    // displaying the result
    fmt.Println("s = ", s)
}


Go
// Golang program to demonstrate
// the use of type inference in
// Pointer variables
package main
 
import "fmt"
 
func main() {
 
    // using var keyword
    // we are not defining
    // any type with variable
    var y = 458
     
    // taking a pointer variable using
    // var keyword without specifying
    // the type
    var p = &y
 
    fmt.Println("Value stored in y = ", y)
    fmt.Println("Address of y = ", &y)
    fmt.Println("Value stored in pointer variable p = ", p)
}


Go
// Golang program to demonstrate
// the use of shorthand syntax in
// Pointer variables
package main
 
import "fmt"
 
func main() {
 
    // using := operator to declare
    // and initialize the variable
    y := 458
     
    // taking a pointer variable using
    // := by assigning it with the
    // address of variable y
    p := &y
 
    fmt.Println("Value stored in y = ", y)
    fmt.Println("Address of y = ", &y)
    fmt.Println("Value stored in pointer variable p = ", p)
}


Go
// Golang program to illustrate the
// concept of dereferencing a pointer
package main
  
import "fmt"
  
func main() {
  
    // using var keyword
    // we are not defining
    // any type with variable
    var y = 458
      
    // taking a pointer variable using
    // var keyword without specifying
    // the type
    var p = &y
  
    fmt.Println("Value stored in y = ", y)
    fmt.Println("Address of y = ", &y)
    fmt.Println("Value stored in pointer variable p = ", p)
 
    // this is dereferencing a pointer
    // using * operator before a pointer
    // variable to access the value stored
    // at the variable at which it is pointing
    fmt.Println("Value stored in y(*p) = ", *p)
 
}


Go
// Golang program to illustrate the
// above mentioned concept
package main
  
import "fmt"
  
func main() {
  
    // using var keyword
    // we are not defining
    // any type with variable
    var y = 458
      
    // taking a pointer variable using
    // var keyword without specifying
    // the type
    var p = &y
  
    fmt.Println("Value stored in y before changing = ", y)
    fmt.Println("Address of y = ", &y)
    fmt.Println("Value stored in pointer variable p = ", p)
 
    // this is dereferencing a pointer
    // using * operator before a pointer
    // variable to access the value stored
    // at the variable at which it is pointing
    fmt.Println("Value stored in y(*p) Before Changing = ", *p)
 
    // changing the value of y by assigning
    // the new value to the pointer
    *p = 500
 
     fmt.Println("Value stored in y(*p) after Changing = ",y)
 
}


输出:

Type of variable x is int
Value of x in hexadecimal is FF
Value of x in decimal is 255
Type of variable y is int
Value of y in hexadecimal is 9C
Value of y in decimal is 156

指针是一种特殊的变量,它不仅用于存储其他变量的内存地址,而且还指向内存所在的位置,并提供查找存储在该内存位置的值的方法。它通常被称为特殊类型的变量,因为它几乎被声明为一个变量,但带有* (取消引用运算符)。

Golang 中的指针

指针的声明和初始化

在我们开始之前,我们将在指针中使用两个重要的运算符,即

  • * 运算符也称为解引用运算符,用于声明指针变量并访问存储在地址中的值。
  • &运算符称为地址运算符,用于返回变量的地址或访问指针的变量地址。

声明一个指针

var pointer_name *Data_Type

示例:下面是一个字符串类型的指针,它只能存储字符串变量的内存地址。

var s *string

指针的初始化:为此,您需要使用地址运算符使用另一个变量的内存地址初始化一个指针,如下例所示:

// normal variable declaration
var a = 45

// Initialization of pointer s with 
// memory address of variable a
var s *int = &a

例子:

// Golang program to demonstrate the declaration
// and initialization of pointers
package main
 
import "fmt"
 
func main() {
 
    // taking a normal variable
    var x int = 5748
     
    // declaration of pointer
    var p *int
     
    // initialization of pointer
    p = &x
 
        // displaying the result
    fmt.Println("Value stored in x = ", x)
    fmt.Println("Address of x = ", &x)
    fmt.Println("Value stored in variable p = ", p)
}

输出:

Value stored in x =  5748
Address of x =  0x414020
Value stored in variable p =  0x414020

要点

1.指针的默认值或零值始终为nil 。或者你可以说一个未初始化的指针总是有一个 nil 值。

例子:

// Golang program to demonstrate
// the nil value of the pointer
package main
 
import "fmt"
 
func main() {
 
        // taking a pointer
    var s *int
     
    // displaying the result
    fmt.Println("s = ", s)
}

输出:

s =  

2.指针的声明和初始化可以在一行中完成。

例子:  

var s *int = &a

3.如果您指定数据类型和指针声明,那么指针将能够处理指定数据类型变量的内存地址。例如,如果您采用字符串类型的指针,那么您将提供给指针的变量地址将仅为字符串数据类型变量,而不是任何其他类型。

4.为了克服上面提到的问题,您可以使用 var 关键字的类型推断概念。声明时无需指定数据类型。指针变量的类型也可以像普通变量一样由编译器确定。这里我们不会使用 *运算符。当我们用另一个变量的地址初始化变量时,它将由编译器在内部确定。

例子:

// Golang program to demonstrate
// the use of type inference in
// Pointer variables
package main
 
import "fmt"
 
func main() {
 
    // using var keyword
    // we are not defining
    // any type with variable
    var y = 458
     
    // taking a pointer variable using
    // var keyword without specifying
    // the type
    var p = &y
 
    fmt.Println("Value stored in y = ", y)
    fmt.Println("Address of y = ", &y)
    fmt.Println("Value stored in pointer variable p = ", p)
}

输出:

Value stored in y =  458
Address of y =  0x414020
Value stored in pointer variable p =  0x414020

5.您还可以使用简写 (:=)语法来声明和初始化指针变量。如果我们使用&(address)运算符将变量的地址传递给它,编译器将在内部确定该变量是一个指针变量。

例子:

// Golang program to demonstrate
// the use of shorthand syntax in
// Pointer variables
package main
 
import "fmt"
 
func main() {
 
    // using := operator to declare
    // and initialize the variable
    y := 458
     
    // taking a pointer variable using
    // := by assigning it with the
    // address of variable y
    p := &y
 
    fmt.Println("Value stored in y = ", y)
    fmt.Println("Address of y = ", &y)
    fmt.Println("Value stored in pointer variable p = ", p)
}

输出:

Value stored in y =  458
Address of y =  0x414020
Value stored in pointer variable p =  0x414020

取消引用指针

正如我们所知, *运算符也称为解引用运算符。它不仅用于声明指针变量,还用于访问存储在指针指向的变量中的值,通常称为间接引用或解引用*运算符也称为 的地址处的值。让我们举一个例子来更好地理解这个概念:

例子:

// Golang program to illustrate the
// concept of dereferencing a pointer
package main
  
import "fmt"
  
func main() {
  
    // using var keyword
    // we are not defining
    // any type with variable
    var y = 458
      
    // taking a pointer variable using
    // var keyword without specifying
    // the type
    var p = &y
  
    fmt.Println("Value stored in y = ", y)
    fmt.Println("Address of y = ", &y)
    fmt.Println("Value stored in pointer variable p = ", p)
 
    // this is dereferencing a pointer
    // using * operator before a pointer
    // variable to access the value stored
    // at the variable at which it is pointing
    fmt.Println("Value stored in y(*p) = ", *p)
 
}

输出:

Value stored in y =  458
Address of y =  0x414020
Value stored in pointer variable p =  0x414020
Value stored in y(*p) =  458

您还可以更改指针或内存位置的值,而不是为变量分配新值。

例子:

// Golang program to illustrate the
// above mentioned concept
package main
  
import "fmt"
  
func main() {
  
    // using var keyword
    // we are not defining
    // any type with variable
    var y = 458
      
    // taking a pointer variable using
    // var keyword without specifying
    // the type
    var p = &y
  
    fmt.Println("Value stored in y before changing = ", y)
    fmt.Println("Address of y = ", &y)
    fmt.Println("Value stored in pointer variable p = ", p)
 
    // this is dereferencing a pointer
    // using * operator before a pointer
    // variable to access the value stored
    // at the variable at which it is pointing
    fmt.Println("Value stored in y(*p) Before Changing = ", *p)
 
    // changing the value of y by assigning
    // the new value to the pointer
    *p = 500
 
     fmt.Println("Value stored in y(*p) after Changing = ",y)
 
}

输出:

Value stored in y before changing =  458
Address of y =  0x414020
Value stored in pointer variable p =  0x414020
Value stored in y(*p) Before Changing =  458
Value stored in y(*p) after Changing =  500