Go 语言指针

Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。

接下来让我们来一步步学习 Go 语言指针。

我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。

Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

以下实例演示了变量在内存中地址:

 package main

 import (
"fmt"
) func main(){
var name string
name = "demon"
fmt.Println("name变量的指针地址:",&name)
}

以上代码运行返回的结果:

name变量的指针地址: 0xc420076050

什么是指针

一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。

类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下:

var var_name(变量名) *var_name_type(数据类型)

var_name就是变量的名称,var_name_type是指针的数据类型,*用于指定变量是一个指针,例如以下的指针声明

var name *string            //指向字符串类型的指针
var age *int //指向整数型类型的指针

如何使用指针

指针使用流程:

  • 定义指针变量。
  • 为指针变量赋值。
  • 访问指针变量中指向地址的值。

在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。

 package main

 import (
"fmt"
) func main(){
//定义局部变量num1 num2
var num1 int =
var num2 *int //获取num1变量的内存地址并赋值给num2变量
num2 = &num1 fmt.Println("num1变量的内存地址为:", &num1)
fmt.Println("num2变量指针的地址为:", num2) //获取变量num1的值
fmt.Println("num1变量的值为:", num1)
//获取变量num2的值
fmt.Println("num2变量的值为:", *num2) }

以上代码返回的运行结果:

num1变量的内存地址为: 0xc42006e178
num2变量指针的地址为: 0xc42006e178
num1变量的值为:
num2变量的值为:

Go 空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil。

nil 指针也称为空指针。

nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

一个指针变量通常缩写为 ptr。

查看以下实例:

 package main

 import (
"fmt"
) func main(){
//初始化局部变量 ptr s 分别都是空指针
var ptr *int
var s *string
//初始化局部变量num1 num2,因为num1赋值了并且num2的指针指向了num1
var num1 float32 = 50.123
var num2 *float32
num2 = &num1 //分别输出变量的值
fmt.Printf("ptr的空指针的值为:%v\n", ptr)
fmt.Printf("s的空指针的值为:%v\n", s)
fmt.Printf("num2的值为%v\n", *num2) //做判断,如果是空指针的话值就是nil
if ptr == nil{
fmt.Println("ptr是空指针哦~")
} if s == nil{
fmt.Println("s是空指针哦~")
} if num2 == nil{
fmt.Println("num2的是空指针哦~")
}else {
fmt.Println("num2的值为:", *num2)
} }

以上代码返回的运行结果:

ptr的空指针的值为:<nil>
s的空指针的值为:<nil>
num2的值为50.
ptr是空指针哦~
s是空指针哦~
num2的值为: 50.123

Go 语言指针数组

number为整型指针数组。因此每个元素都指向了一个值。以下实例的三个整数将存储在指针数组中:

 package main

 import (
"fmt"
) func main(){
//定义一个blance数组,并且拥有五个元素
var blance = [] int {,,,,}
//定义常量MAX为5
const MAX int =
//定义数组指针number
var number [MAX] *int for i := ; i< MAX; i++{
//分别给number的数组中的每个索引赋值,值是引用blance数组中的每个元素的内存地址
number[i] = &blance[i]
fmt.Printf("blance[%d] = %d \n", i, blance[i])
} fmt.Println("----------------------") for i := ; i< MAX; i++{
fmt.Printf("number[%d] = %d \n", i, *number[i])
} fmt.Println("----------------------") for i := ; i< MAX; i++{
//如果blance数组与number数组一样,并且里面只的内存地址都一样,则打印两个数组元素的内存地址
if blance[i] == *number[i] && &blance[i] == number[i]{
fmt.Printf("blance[%d] %v number[%d] %v \n",i , &blance[i], i ,number[i]) }
}
}

以上代码返回的运行结果:

blance[] =
blance[] =
blance[] =
blance[] =
blance[] =
----------------------
number[] =
number[] =
number[] =
number[] =
number[] =
----------------------
blance[] 0xc4200141e0 number[] 0xc4200141e0
blance[] 0xc4200141e8 number[] 0xc4200141e8
blance[] 0xc4200141f0 number[] 0xc4200141f0
blance[] 0xc4200141f8 number[] 0xc4200141f8
blance[] 0xc420014200 number[] 0xc420014200

来来来来,用Python来嘲讽一波golang的数组引用赋值~

 #!/usr/bin/env python3
# _*_coding:utf-8_*_ __author__ = 'demon' #声明列表l1
l1 = ['demon','','beijing',"python","golang","linux"]
#浅拷贝列表l1中的每个元素
l2 = l1[:] l1_len = len(l1) for i in range(l1_len):
#判断列表中每个元素的内存地址是否一致
if id(l1[i]) == id(l2[i]):
#打印两个列表中给的每个元素及内存地址
print("l1[{}] {:10} l2[{}] {:10} at {memory}".format(i,l1[i],i,l2[i],memory=id(l1[i])))

以上代码返回的运行结果:

l1[0]   demon        l2[0]  demon      at 4302152624
l1[1] 18 l2[1] 18 at 4330894536
l1[2] beijing l2[2] beijing at 4330894200
l1[3] python l2[3] python at 4329981408
l1[4] golang l2[4] golang at 4330894984
l1[5] linux l2[5] linux at 4329974728

Go 语言指向指针的指针

如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。

当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:

指向指针的指针变量声明格式如下:

var ptr **int;

以上指向指针的指针变量为整型。

访问指向指针的指针变量值需要使用两个 * 号,如下所示:

 package main

 import (
"fmt"
) func main() { var a int
var ptr *int
var pptr **int a = //指针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 =
指针变量 *ptr =
指向指针的指针变量 **pptr =

Go 语言指针作为函数参数

Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。

以下实例演示了如何向函数传递指针,并在函数调用后修改函数内的值:

 package main

 import (
"fmt"
) //可以接收指针作为参数的自定义函数
func person(name *string,age *int) string {
//修改指针指向的name变量的值,影响了name的值
*name = "大佬"
fmt.Println("person函数内部的name的内存地址:", name)
fmt.Printf("person函数内部的修改后name变量值:%s", *name)
return "" } func swap(x ,y int) string{
//修改x,y的值,x,y作为局部变量传递进来,因为没有使用指针,所以不会影响函数外部的x,y变量值
x, y = ,
fmt.Println("swap函数内部的x变量值:", x)
fmt.Println("swap函数内部的y变量值:", y)
return ""
} func main() {
//初始化局部变量
var name string = "demon"
var age int =
var x int =
var y int = fmt.Println("person函数内部的修改后name变量值:", name)
fmt.Println("person函数外部的name的内存地址:", &name)
fmt.Println(person(&name, &age))
fmt.Printf("person函数外部的修改后name变量值:%s \n",name) fmt.Println("--------------------------------------------")
fmt.Println(swap(x,y ))
fmt.Println("swap函数外部的x变量值:", x)
fmt.Println("swap函数外部的y变量值:", y) }

以上代码返回的运行结果:

person函数内部的修改后name变量值: demon
person函数外部的name的内存地址: 0xc42006e1a0
person函数内部的name的内存地址: 0xc42006e1a0
person函数内部的修改后name变量值:大佬
person函数外部的修改后name变量值:大佬
--------------------------------------------
swap函数内部的x变量值:
swap函数内部的y变量值: swap函数外部的x变量值:
swap函数外部的y变量值:

Go指针的更多相关文章

  1. TODO:Golang指针使用注意事项

    TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...

  2. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  3. C++虚函数和函数指针一起使用

    C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...

  4. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  5. c 数组与指针的使用注意事项

    数组变量和指针变量有一点小小的区别 所以把数组指针赋值给指针变量的时候千万要小心 加入把数组赋值给指针变量,指针变量只会包含数组的地址信息 而对数组的长度一无所知 相当于指针丢失了一部分信息,我们把这 ...

  6. Marshal.Copy将指针拷贝给数组

    lpStatuss是一个UNITSTATUS*的指针类型实例,并包含SensorDust字段 //定义一个数组类型 byte[] SensorDust = new byte[30] //将指针类型拷贝 ...

  7. C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...

  8. EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针

    一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...

  9. 智能指针shared_ptr的用法

    为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...

  10. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

随机推荐

  1. 拥抱.NET Core系列:依赖注入(2)

    上一篇"拥抱.NET Core系列:依赖注入(1)"大体介绍了服务注册.获取和生命周期,这一篇来做一些补充. 由于内容跨度大(.NET Core.ASP.NET Core),所以文 ...

  2. Android反编译odex然后重新打包

    #Android反编译odex然后重新打包 最近不知道怎么回事,突然把我那刷了氧OS的root了,然后就开始好奇起来氢OS所带有的那些本地化的东西,比如通话录音就是典型的一个之一.其中也做了很多的尝试 ...

  3. JavaScript创建对象的方法

    显示在浏览器中的控制台中. <script type="text/javascript"> //这个工厂方法返回一个新的"范围对象" functio ...

  4. MySql单表最大8000W+ 之数据库遇瓶颈记

    前言 昨晚救火到两三点,早上七点多醒来,朦胧中醒来发现电脑还开着,赶紧爬起来看昨晚执行的SQL命令结果.由于昨晚升级了阿里云的RDS,等了将近两个小时 还在 升降级中,早上阿里云那边回复升级过程中出现 ...

  5. 51nod_1627:瞬间移动

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1627 还是杨辉三角~ #include<bits/st ...

  6. (转)Linux系统安装时分区的选择

    场景:对于Linux系统的分区总是迷迷茫茫的,还是实践少,基础不牢. 以前初识Linux时,对Linux系统安装时分区的选择,一点都不了解,导致几次没法进行下一步安装,因此就静下心来,专门拿出时间研究 ...

  7. Eclipse详细设置护眼背景色和字体颜色并导出

    Eclipse详细设置护眼背景色和字体颜色并导出 Eclipse是一款码农们喜闻乐见的集成开发平台,但是其默认的主题和惨白的背景色实在是太刺激眼球了.下面,将给大家详细介绍如何设置成护眼主题的方法,也 ...

  8. 聊聊synchronized的锁问题

    本文不会特别深入细致地讨论synchronized,只是做一个通俗易懂的说明,以及看清一类问题的本质,希望能给大家一点启发. 问题描述 有一个类A,提供了三个方法.分别是静态同步方法,非静态同步方法, ...

  9. vue项目优化之按需加载组件-使用webpack require.ensure

    require-ensure和require-amd的区别: require-amd 说明: 同AMD规范的require函数,使用时传递一个模块数组和回调函数,模块都被下载下来且都被执行后才执行回调 ...

  10. Nlpir Parser智能语义平台全文搜索

    全文索引用于处理大文本集合,利用它人们可以在海量文本中快速获取需要的信息.全文检索系统是按照全文检索理论建立起来的用于提供全文检索服务的软件系统.一般来说,全文检索需要具备建立索引和提供查询的基本功能 ...