当前位置:网站首页>By asking where the variables are stored, the shepherd boy laughed and said to use pointers, Go lang1.18 introductory refining tutorial, from Bai Ding to Hongru, the use of go lang type pointers (Poin

By asking where the variables are stored, the shepherd boy laughed and said to use pointers, Go lang1.18 introductory refining tutorial, from Bai Ding to Hongru, the use of go lang type pointers (Poin

2022-08-09 10:04:00 User 9127725

    what is the pointer?指针是存储另一个变量的内存地址的变量.变量是一种使用方便的占位符,用于引用计算机内存地址,一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址.类比的话,A pointer is a table of contents in a book,Also occupy the page itself,You can get the chapter content through the table of contents,It can also point to the number of pages of a specific chapter(地址).

    指针声明

    声明指针,*T是指针变量的类型,它指向T类型的值:

var var_name *var-type

    var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针.

    例如:

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮点型 */

    before we used to use&keyword to get the address of a variable in memory,事实上,the object is the pointer:

package main

import "fmt"

func main() {
	var a int = 20 /* 声明实际变量 */
	var ip *int    /* 声明指针变量 */

	ip = &a /* 指针变量的存储地址 */

	fmt.Printf("a 变量的地址是: %x\n", &a)

	/* 指针变量的存储地址 */
	fmt.Printf("ip 变量的存储地址: %x\n", ip)

	/* 使用指针访问值 */
	fmt.Printf("*ip 变量的值: %d\n", *ip)
}

    由此可见,指针变量的类型为 *Type,该指针指向一个 Type 类型的变量.The most obvious feature of the pointer variable is a real variables stored memory address,By recording the address of a variable,thus indirectly manipulate the variable.

    & keyword can get its memory address from a variable.

    * keyword if on the left side of the value of the assignment operation,refers to the variable pointed to by this pointer;* keyword if on the right side of the assignment operator,Refers to getting the value of a variable from a pointer variable,Also known as pointer reference solution.

    Pointers are also divided into different types:

package main

import "fmt"

func main() {
	mystr := "字符串"
	myint := 1
	mybool := false
	myfloat := 3.2
	fmt.Printf("type of &mystr is :%T\n", &mystr)
	fmt.Printf("type of &myint is :%T\n", &myint)
	fmt.Printf("type of &mybool is :%T\n", &mybool)
	fmt.Printf("type of &myfloat is :%T\n", &myfloat)
}

    程序返回:

type of &mystr is :*string
type of &myint is :*int
type of &mybool is :*bool
type of &myfloat is :*float64

    但其实,指针的类型,In fact, it is the basic type of the variable it refers to,Both types are the same.

    空指针

    Go langA null pointer is when a pointer is defined and not assigned to any variable,它的值为 nil. nil 指针也称为空指针. nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值. 一个指针变量通常缩写为 ptr:

if(ptr != nil)     /* ptr 不是空指针 */
if(ptr == nil)    /* ptr 是空指针 */

    具体例子:

package main

import "fmt"

func main() {
	x := "字符串"
	var ptr *string
	fmt.Println("ptr is ", ptr)
	ptr = &x
	fmt.Println("ptr is ", ptr)
}

    程序返回:

ptr is  <nil>
ptr is  0xc00003c250

    但也需要注意的是,The null value of a pointer is the same as the null value of a variable,need to use identity or non-identity to judge,而并非像Python一样使用iskeyword to compare the specific address of memory.

    指针操作

    Getting a pointer means accessing the value of the variable pointed to by the pointer.语法是:*a

package main

import (
	"fmt"
)

func main() {
	b := 255
	a := &b
	fmt.Println("address of b is", a)
	fmt.Println("value of b is", *a)
}

    程序返回:

address of b is 0xc000014088
value of b is 255

    一般情况下,We can change the value of a variable by secondary assignment,Now it's also possible to pass pointers:

package main

import (
	"fmt"
)

func main() {
	b := 255
	a := &b
	fmt.Println("address of b is", a)
	fmt.Println("value of b is", *a)
	*a++
	fmt.Println("new value of b is", b)
}

    程序返回:

address of b is 0xc0000aa058
value of b is 255
new value of b is 256

    This value needs to be incremented by incrementing the pointer,就可以修改变量b的值.

    与此同时,在传参过程中,也可以使用指针:

package main

import (
	"fmt"
)

func change(val *int) {
	*val = 55
}
func main() {
	a := 58
	fmt.Println("value of a before function call is", a)
	b := &a
	change(b)
	fmt.Println("value of a after function call is", a)
}

    程序返回:

value of a before function call is 58
value of a after function call is 55

    众所周知,intis value type data,If passed into method scope via variable,Method within the scope of operation is in fact another object,比如:

package main

import (
	"fmt"
)

func change(val int) {
	val = 55
}
func main() {

	b := 58
	change(b)
	fmt.Println("value of a after function call is", b)
}

    返回:

value of a after function call is 58

    But if the process using a pointer,将aThe variable pointer object is passed into the method,The modification in the method is actually the memory address variable,In this way, the value of the value type object can be changed accordingly,Saves additional memory application space.

    Suppose we want to make some modifications to the array inside the method,and changes made to the array inside the method are visible to the caller.One way is to put a pointer to an array is passed to the method:

package main

import (
	"fmt"
)

func modify(arr *[3]int) {
	(*arr)[0] = 90
}

func main() {
	a := [3]int{89, 90, 91}
	modify(&a)
	fmt.Println(a)
}

    程序返回:

[90 90 91]

    Although you can use a pointer to an array as a method of argument and modify it,But that doesn't mean we have to do it,Because slices can also be used:

package main

import (
	"fmt"
)

func modify(sls []int) {
	sls[0] = 90
}

func main() {
	a := [3]int{89, 90, 91}
	modify(a[:])
	fmt.Println(a)
}

    程序返回:

[90 90 91]

    As reference for slicing and pointer types,If we want to change the value of an array through a function,You can pass a slice of the array as a parameter to a function,You can also pass a pointer to this array as a parameter to a function,显而易见,Easier to use slices.

    此外,Pointers can also have pointers,也就是说,Pointers can also point to memory addresses where other pointers are located:

package main

import "fmt"

func main() {

	var a int
	var ptr *int
	var pptr **int

	a = 3000

	/* 指针 ptr 地址 */
	ptr = &a

	/* 指向指针 ptr 地址 */
	pptr = &ptr

	/* 获取 pptr 的值 */
	fmt.Printf("变量 a = %d\n", a)
	fmt.Printf("指针变量 *ptr = %d\n", *ptr)
	fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
}

    程序返回:

变量 a = 3000
指针变量 *ptr = 3000
指向指针的指针变量 **pptr = 3000

    这里指针pptr指向指针ptr,指针ptr执行变量a

    When we change the pointer value of the pointer:

package main

import "fmt"

func main() {

	var a int
	var ptr *int
	var pptr **int

	a = 3000

	/* 指针 ptr 地址 */
	ptr = &a

	/* 指向指针 ptr 地址 */
	pptr = &ptr

	/* 获取 pptr 的值 */
	fmt.Printf("变量 a = %d\n", a)
	fmt.Printf("指针变量 *ptr = %d\n", *ptr)
	fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)

	**pptr = 200

	fmt.Printf("变量 a = %d\n", a)
	fmt.Printf("指针变量 *ptr = %d\n", *ptr)
	fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
}

    程序返回:

变量 a = 3000
指针变量 *ptr = 3000
指向指针的指针变量 **pptr = 3000
变量 a = 200
指针变量 *ptr = 200
指向指针的指针变量 **pptr = 200

    A chain reaction can be seen,Both the starting point and the final point have changed,可谓是牵一发而动全身,事实上,Pointer operations are faster than repeated assignments.

    结语

    简而言之,Many compiled languages ​​actually have pointers,c/c++is the real pointer,而Javais actually a reference to a pointer,It can be understood that the value of the pointer cannot be manipulated,pointers that do not allow pointer arithmetic.现实问题是,go lang这种“次时代”new trend programming language,为什么不像Java那样,仅仅实现“引用”,but must give“指针”the substantive concept of?

    在Go lang官网文档中,Can get some clues:

In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution. 文档地址:https://go.dev/ref/spec#Calls

    一望而知,go lang的设计者们在go langexist in grammatical design“perfectionism obsessive-compulsive disorder”,Method parameters are absolute value-by-value,Go langThe method and a way to pass only value,不存在引用传递,这样一来,must have an explicit pointer type,To ensure that the object can be modified under the premise of passing the value.

   其实 Pythonalso compromised here,Variable data types for reference,但go langstraight man of steel,would rather add more complex pointer logic,Also thoroughly implement pass-by-value logic,for the purpose of using pointers where appropriate, Gains in program speed and memory consumption.

原网站

版权声明
本文为[User 9127725]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/221/202208090943258934.html