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. vijos1034题解

    题目: 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系. 规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚.如果x,y是亲 ...

  2. FZU 1015 土地划分

        Description 在Dukeswood这块土地上生活着一个富有的农庄主和他的几个孩子.在他临终时,他想把他的土地分给他的孩子.他有许多农场,每个农场都是一块矩形土地.他在农场地图上划上一 ...

  3. 【SqlServer系列】表连接

    1   概述 1.1  已发布[SqlServer系列]文章 [SqlServer系列]MYSQL安装教程 [SqlServer系列]数据库三大范式 [SqlServer系列]表单查询 1.2  本篇 ...

  4. Struts2框架05 result标签的类型

    1 result标签是干什么的 就是结果,服务器处理完返回给浏览器的结果:是一个输出结果数据的组件 2 什么时候需要指定result标签的类型 把要输出的结果数据按照我们指定的数据类型进行处理 3 常 ...

  5. AugularJS从入门到实践(二)

      前  言  前端    AngularJS是为了克服HTML在构建应用上的不足而设计的.(引用百度百科) 本篇学习主要有两个部分: ①[AngularJS 过滤器]   ②[AngularJS  ...

  6. 谈谈HashMap与HashTable

    谈谈HashMap与HashTable HashMap 我们一直知道HashMap是非线程安全的,HashTable是线程安全的,可这是为什么呢?先聊聊HashMap吧,想要了解它为什么是非线程安全的 ...

  7. Javascript百学不厌-递归

    虽然偶尔也用过,但是从来没具体来整理过 普通递归: function fac(n) { ) ; ); } fac() 这是个阶乘.但是占用内存,因为: fac(5) (5*fac(4)) (5*(4* ...

  8. U盘发现器

    U盘发现器 package com.lx.io; import java.io.File; import java.io.IOException; import java.util.ArrayList ...

  9. 20170717_python_爬虫_网页数据解析_BeautifulSoup_数据保存_pymysql

    上午废了老大劲成功登陆后,下午看了下BeautifulSoup和pymysql,晚上记录一下 自己电脑装的sublime,字体颜色竟然拷贝不下来 - - 写的过程中遇到了很多问题: 1.模拟登陆部分 ...

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

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