热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

换个语言学一下Golang(8)——指针

定义所谓指针其实你可以把它想像成一个箭头,这个箭头指向(存储)一个变量的地址。因为这个箭头本身也需要变量来存储,所以也叫做指针变量。Go的指针不支持那些乱七八糟的指针移位。它就表示一个变量

定义

所谓指针其实你可以把它想像成一个箭头,这个箭头指向(存储)一个变量的地址

因为这个箭头本身也需要变量来存储,所以也叫做指针变量。

Go的指针不支持那些乱七八糟的指针移位它就表示一个变量的地址。看看这个例子:

package main
import (
    "fmt"
)
func main() {
    var x int
    var x_ptr *int
    x = 10
    x_ptr = &x
    fmt.Println(x)
    fmt.Println(x_ptr)
    fmt.Println(*x_ptr)
}

上面例子输出x的值x的地址通过指针变量输出x的值,而x_ptr就是一个指针变量

10
0xc084000038
10

认真理清楚这两个符号的意思。

取一个变量的地址

取一个指针变量所指向的地址的值

考你一下,上面的例子中,如何输出x_ptr的地址呢?

package main
import (
    "fmt"
)
func main() {
    var x int
    var x_ptr *int
    x = 10
    x_ptr = &x
    fmt.Println(&x_ptr)
}

此例看懂,指针就懂了。

永远记住一句话,所谓指针就是一个指向(存储)特定变量地址的变量。没有其他的特别之处。

再变态一下,看看这个:

package main
import (
    "fmt"
)
func main() {
    var x int
    var x_ptr *int
    x = 10
    x_ptr = &x
    fmt.Println(*&x_ptr)
}
  1. x_ptr 是一个指针变量,它指向(存储)x的地址
  2. &x_ptr 是取这个指针变量x_ptr的地址,这里可以设想有另一个指针变量x_ptr_ptr(指向)存储这个x_ptr指针的地址
  3. &x_ptr 等价于`x_ptr_ptr就是取这个x_ptr_ptr指针变量指向(存储)地址所对应的变量的值,也就是x_ptr的值,也就是指针变量x_ptr指向(存储)的地址,也就是x的地址。 这里可以看到,其实*&`这两个运算符在一起就相互抵消作用了。
用途

指针的一大用途就是可以将变量的指针作为实参传递给函数,从而在函数内部能够直接修改实参所指向的变量值。

Go的变量传递都是值传递。

package main
import (
    "fmt"
)
func change(x int) {
    x = 200
}
func main() {
    var x int = 100
    fmt.Println(x)
    change(x)
    fmt.Println(x)
}

上面的例子输出结果为

100
100

很显然,change函数改变的仅仅是内部变量x,而不会改变传递进去的实参。其实,也就是说Go的函数一般关心的是输出结果,而输入参数就相当于信使跑到函数门口大叫,你们这个参数是什么值,那个是什么值,然后就跑了。你函数根本就不能修改它的值。不过如果是传递的实参是指针变量,那么函数一看,小子这次你地址我都知道了,哪里跑。那么就是下面的例子:

package main
import (
    "fmt"
)
func change(x *int) {
    *x = 200
}
func main() {
    var x int = 100
    fmt.Println(x)
    change(&x)
    fmt.Println(x)
}

上面的例子中,change函数的虚参为整型指针变量,所以在main中调用的时候传递的是x的地址。然后在change里面使用*x=200修改了这个x的地址的值。所以x的值就变了。这个输出是:

100
200
new

new这个函数挺神奇,因为它的用处太多了。这里还可以通过new来初始化一个指针。上面说过指针指向(存储)的是一个变量的地址,但是指针本身也需要地址存储。先看个例子:

package main
import (
    "fmt"
)
func set_value(x_ptr *int) {
    *x_ptr = 100
}
func main() {
    x_ptr := new(int)
    set_value(x_ptr)
    //x_ptr指向的地址
    fmt.Println(x_ptr)
    //x_ptr本身的地址
    fmt.Println(&x_ptr)
    //x_ptr指向的地址值
    fmt.Println(*x_ptr)
}

上面我们定义了一个x_ptr变量,然后用new申请了一个存储整型数据的内存地址,然后将这个地址赋值x_ptr指针变量,也就是说x_ptr指向(存储)的是一个可以存储整型数据的地址,然后用set_value函数将这个地址中存储的值赋值为100。所以第一个输出是x_ptr指向的地址,第二个则是x_ptr本身的地址,而*x_ptr则是x_ptr指向的地址中存储的整型数据的值

0xc084000040
0xc084000038
100
小结

好了,现在用个例子再来回顾一下指针。

交换两个变量的值。

package main
import (
    "fmt"
)
func swap(x, y *int) {
    *x, *y = *y, *x
}
func main() {
    x_val := 100
    y_val := 200
    swap(&x_val, &y_val)
    fmt.Println(x_val)
    fmt.Println(y_val)
}

很简单吧,这里利用了Go提供的交叉赋值的功能,另外由于是使用了指针作为参数,所以在swap函数内,x_val和y_val的值就被交换了。

 

 

 

                        
                        
                         
推荐阅读
  • 按照之前我对map的理解,map中的数据应该是有序二叉树的存储顺序,正常的遍历也应该是有序的遍历和输出,但实际试了一下,却发现并非如此,网上查了下,发现从Go1开始,遍历的起始节点就是随机了,当然随机 ... [详细]
  • 认真一点学 Go:18. 并发
    收录于《Go基础系列》,作者:潇洒哥老苗。>>原文链接学到什么并发与并行的区别?什么是Goroutine?什么是通道?Goroutine如何通信?相关函数的使用?sel ... [详细]
  • golang 解析磁力链为 torrent 相关的信息
    其实通过http请求已经获得了种子的信息了,但是传播存储种子好像是违法的,所以就存储些描述信息吧。之前python跑的太慢了。这个go并发不知道写的有没有问题?!packag ... [详细]
  • Go冒泡排序练习
    package main要求:随机生成5个元素的数组,并使用冒泡排序对其排序  从小到大思路分析:随机数用mathrand生成为了更好 ... [详细]
  • Go 快速入门指南命令行参数
    命令行参数个数调用os包即可。获取参数个数,遍历参数packagemainimport(fmtos)funcmain(){fmt.Printf(Numberofargsi ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 本文介绍了在多平台下进行条件编译的必要性,以及具体的实现方法。通过示例代码展示了如何使用条件编译来实现不同平台的功能。最后总结了只要接口相同,不同平台下的编译运行结果也会相同。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • (三)多表代码生成的实现方法
    本文介绍了一种实现多表代码生成的方法,使用了java代码和org.jeecg框架中的相关类和接口。通过设置主表配置,可以生成父子表的数据模型。 ... [详细]
  • 目录在Go语言项目中使用Zap日志库介绍默认的GoLogger日志库实现GoLogger设置Logger使用LoggerLogger的运行GoLogger的优势和劣势优势劣势Ube ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 数组的排序:数组本身有Arrays类中的sort()方法,这里写几种常见的排序方法。(1)冒泡排序法publicstaticvoidmain(String[]args ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
author-avatar
you_only89
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有