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. CSS学习(页外引用还不懂)

    CSS的语法结构为   选择符 {属性:值:}    Selector {Property : Value:} 选择符:通配 *{....}  , 元素  body{....} .h1{....}.p ...

  2. Mac之OS系统下搭建JavaEE环境 <四> 之IntelliJ IDEA 的内存优化

    1.代开IntelliJ IDEA 的显示内容 2. 打开idea.vmoptions文件 路径为Contens——bin——idea.vmoptions 修改之前会复制一份备份原配置 原配置 修改后 ...

  3. 接口开发,tp5结合swagger-ui安装方法

    今天看到老java用的swagger提供接口,美观好用,方便维护,不是写好接口之后再写接口文档,麻烦的要死.网上找了找结合php的方法,在此记录一下,以后再开发接口就可以方便很多了. Swagger的 ...

  4. Html5元素布局

    本教程十分简单,适合新手(因为我也是新手).本教程参考了"菜鸟教程". 笔者希望做到元素相对于浏览器的角落布局,即九个典型位置: 这个理念其实和UE4中的UMG锚定一样.Html5 ...

  5. 是什么优化让 .NET Core 性能飙升?

    .NET Core(开放源代码,跨平台,x-copy可部署等)有许多令人兴奋的方面,其中最值得称赞的就是其性能了. 感谢所有社区开发人员对.NET Core做出的贡献,其中的许多改进也将在接下来的几个 ...

  6. MyBatis的关联关系补充 多对多 继承

    多对多 一个学生有多个课程 一个课程有多个学生 思路分析 :使用一个中间表 用学生表和课程表的主键作为中间表的联合主键 1数据库表的设计 课程表 学生表 中间表 2/实体类的设计 课程类 public ...

  7. SparkMLlib-----GMM算法

    Gaussian Mixture Model(GMM)是一个很流行的聚类算法.它与K-Means的很像,但是K-Means的计算结果是算出每个数据点所属的簇,而GMM是计算出这些数据点分配到各个类别的 ...

  8. 第2章 rsync算法原理和工作流程分析

    本文通过示例详细分析rsync算法原理和rsync的工作流程,是对rsync官方技术报告和官方推荐文章的解释. 以下是本文的姊妹篇: 1.rsync(一):基本命令和用法 2.rsync(二):ino ...

  9. Multimodal —— 看图说话(Image Caption)任务的论文笔记(一)评价指标和NIC模型

    看图说话(Image Caption)任务是结合CV和NLP两个领域的一种比较综合的任务,Image Caption模型的输入是一幅图像,输出是对该幅图像进行描述的一段文字.这项任务要求模型可以识别图 ...

  10. Hibernate 实体关联关系映射----总结

    在我看来,Hibernate提供这些映射关系,常用就是一对一和多对一,并且在能不用连接表的时候尽量不要用连接表.多对多会用到,如果用到了,应该首先考虑底层数据库设计是否合理.   在实际开发中,在Hi ...