golang的指针

Posted 404space

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang的指针相关的知识,希望对你有一定的参考价值。

在说golang的指针之前,先啰嗦一下关于计算机的东西。众所周知,1TB=1024GB,1GB=1024MB,1MB=1024KB,1KB=1024字节。
技术分享图片

                  go中int类型的大小(引自《Go语言编程》)

在go语言中,内存是自动分配的,也就是说,我声明一个变量,go的编译器会根据你声明的变量类型来自动分配适当的内存(这里不涉及内存分配的东西,会在后续的文章中来介绍)

技术分享图片

此时,声明并初始化一个int类型的变量a = 2

package main

import "fmt"

func main() {
	var a int = 2
	c := a
	fmt.Printf("a的内存地址:%x
",&a)
	fmt.Printf("c的内存地址:%x
",&c)
} 

运行后发现技术分享图片a和c指向同一块内存地址。

此时,修改c,令其等于另一个值

package main

import "fmt"

func main() {
	var a int = 2
	c := a
	fmt.Printf("a的内存地址:%x
",&a)
	fmt.Printf("c的内存地址:%x
",&c)
	//修改c的值
	c = 12
	fmt.Printf("修改之后c的内存地址:%x
",&c)

}

  运行之后发现,技术分享图片,说明此时c指向了另一个内存地址。

                                                             技术分享图片

这一点明白之后,我们来看golang的指针。

package main

import "fmt"

func main() {
	var a int = 2
	var pa *int = &a
	fmt.Printf("a的内存地址是:%x
",&a)
	fmt.Printf("pa的内存地址是:%x
",pa)
}
在go语言中,&为取地址符,用来获取某个类型变量的地址,我们可以叫pa *int为一个int类型的指针,所以这句话可以理解为:让一个名为pa的int类型的指针,指向a的内存地址。运行之后发现:

技术分享图片

a和pa的内存地址相同。(pa保存的值是一个地址)我们可以使用*pa来修改这个变量指向的地址的值。

import "fmt"

func main() {
var a int = 2
var pa *int = &a //一个名叫pa的int型指针指向a的地址
fmt.Printf("修改前a的内存地址是:%x ",&a)
fmt.Printf("修改前pa的内存地址是:%x ",pa)
//修改值
*pa = 5
fmt.Printf("修改后a的内存地址是:%x ",&a)
fmt.Printf("修改后pa的内存地址是:%x ",pa)
fmt.Println("a的值是:",a)
fmt.Println("*pa的值是:",*pa)
}

 运行后发现 技术分享图片修改之后,原变量a的值和*pa的值相同,a的内存地址是原始的内存地址且和pa保存的内存地址也相同,所以此次修改了原来a内存地址中保存的数值。

接下来我们看一下参数传递。在c和c++可以值传递,也可以引用传递;java和python绝大多数为引用传递。那么在go中是使用的什么方式呢?其实,Go只有值传递一种方式,但是我们可以使用指针的方式来协助。

package main

import "fmt"

func incresment(a int)  {
	a += 1
	fmt.Println("自增后的值为:",a)
}

func main() {
	a := 5
	incresment(a)
	fmt.Println("a的值为:",a)
}

  运行后可以发现技术分享图片go使用的是值传递的方式,也就是说,将参数做了一次拷贝。

看到这儿可能有的人会问:函数中参数比较少还好,如果有很多参数,岂不是要浪费很多时间?回过头来看看,前边说过了,可以使用指针来作辅助。

我们再来看一个例子:

package main

import "fmt"

func swap(a, b int)  {
	var temp int
	temp = a
	a = b
	b = temp
	fmt.Println("交换后a的值是:",a)
	fmt.Println("交换后b的值是:",b)
}

func main() {
	a := 5
	b := 6
	swap(a,b)
	fmt.Println("a的值是:",a)
	fmt.Println("b的值是:",b)
}

  因为go是值传递的方式,所以运行后技术分享图片只在swap()函数的作用域内正确,此时我们借助指针来实现这个交换位置的函数

package main

import "fmt"

func swap(a, b *int)  {
	var temp int
	temp = *a
	*a = *b
	*b = temp
}

func main() {
	a := 5
	b := 6
	fmt.Println("交换前a的值是:",a)
	fmt.Println("交换前b的值是:",b)
	fmt.Println("------------------")
	swap(&a,&b)
	fmt.Println("交换后a的值是:",a)
	fmt.Println("交换后b的值是:",b)
}

  swap函数中的参数是两个int类型的指针,前边提到了,这个指针应该指向一个内存地址,所以在main函数中调用swap时需要传入a和b的地址,此时的执行结果是技术分享图片也就是说,如果我们需要对原数据进行修改的话,需要使用指针,这在数据结构和算法中会经常用到。

 

 

 

 

 

 

 


 

                

 















以上是关于golang的指针的主要内容,如果未能解决你的问题,请参考以下文章

代码片段 - Golang 实现简单的 Web 服务器

代码片段 - Golang 实现集合操作

#yyds干货盘点#带大家认识Golang中的切片数据类型

json [Golang] golang #golang #snippets中有用的片段

Golang 指向切片的指针

将 nil 接口转换为 Golang 中的指针?