一、指针与引用的相关概念

什么是指针?

  指针,全称为指针变量,是用来存储内存地址的一种变量。程序中,一般通过指针来访问其指向的内存地址中的内容(数据)。

什么是引用?

  引用,是C++中提出来的一种新的使用变量的方式,即,给实际变量起个别名,通过这个别名来引用实际的变量。标准C中不支持变量的引用。

指针与引用的区别?

  1.指针是实实在在的变量,有自己的内存存储空间,它可以指向任何有效的变量。

  2.引用是一种形式、方法,定义的引用变量,实际上是原实际变量的另一个名称(别名),引用变量本身没有自己的实际存储空间,操作引用变量,就是在操作实际变量。

go语言的指针与c语言指针,以及java,python等引用类型的语言的区别与联系:

  1.Java,Python,Javascript 等引用类型的语言

  2.Golang 的指针是单独的类型,而不是 C 语言中的 int 类型,而且也不能对指针做整数运算。

  3.从这一点看,Golang 的指针基本就是一种引用。

对引用类型语言来说,参数传递时,什么时候传值,什么时候传引用?

  1.在大部分引用型语言里,参数为基本类型时,传进去的大都是值,也就是另外复制了一份参数到当前的函数调用栈。

  2.参数为高级类型时,传进去的基本都是引用。这个主要是因为虚拟机的内存管理导致的。

传值和传引用的区别?

  1.内存管理中的内存区域一般包括 heap 和 stack, stack 主要用来存储当前调用栈用到的简单类型数据:string,boolean,int,float 等。

  2.这些类型的内存占用小,容易回收,基本上它们的值和指针占用的空间差不多,因此可以直接复制,GC也比较容易做针对性的优化。

  3.复杂的高级类型占用的内存往往相对较大,存储在 heap 中,GC 回收频率相对较低,代价也较大,因此传引用/指针可以避免进行成本较高的复制操作,并且节省内存,提高程序运行效率。

而在 Golang 中,具体到高级类型 struct,slice,map,也各有不同。实际上,只有 struct 的使用有点复杂,slice,map,chan 都可以直接使用,不用考虑是值还是指针。

二、go语言指针介绍

go的原生数据类型分类:

  1.基本类型:string, bool, int, float等           使用值传递

  2.高级类型:sturuct, array/slice, map, chan, func。     使用引用传递

go的指针定义:

    a.一个指针的值是另一个变量的地址。

  b.一个指针对应变量在内存中的存储位置。

  c.并不是每一个值都会有一个内存地址。

  d.灭一个变量必然有对应的内存地址。     

   e.用过指针我们可以直接读或者更新对应变量的值,而不需要知道该变量的名字。

go语言中,什么时候使用指针?(指针使用的场景):

  1.需要改变参数的值

  2.避免复制操作

  3.节省内存

go语言的值传递和“引用传递”

  1.go语言中的传递方式只有值传递

  2.所谓的“引用传递”是指将要传递的较大的值,复制他的内存地址然后将内存地址通过值传递传给对象。对象拿到内存地址的值就可以直接访问了。这个过程看起来很像“引用传递”

指针(pointer)在go 语言中拆分为两个核心概念:

  1.类型指针,允许对这个指针类型的数据进行修改。传递数据使用指针,而无需拷贝数据。类型指针不能进行偏移量和运算。

  2.切片,由指向起始元素的原始指针、元素数量和容量组成。

go语言指针的优势:

  1.Go 语言的指针类型变量拥有指针的高效访问

  2.不会发生指针偏移,从而避免非法修改关键性数据问题。

  3.垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。

  4.切片比原始指针具备更强大的特性,更为安全。

  5.切片发生越界时,运行时会报出宕机,并打出堆栈,而原始指针只会崩溃。

指针类型和指针地址:

  1.每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置

  2.Go 语言中使用 & 作符放在变量前面对变量进行“取地址”操作。

ptr := &v    // v的类型为T

  v 代表被取地址的变量

  变量prt 接收 被取地址的 v

  ptr 的类型就为*T,称做 T 的指针类型。*代表指针。

package main
import (
"fmt"
)
func main() {
//声明整型 cat 变量。
var cat int = 1
//声明字符串 str 变量。
var str string = "banana"
//使用 fmt.Printf 的动词%p输出 cat 和 str 变量取地址后的指针值,指针值带有0x的十六进制前缀。
fmt.Printf("%p %p", &cat, &str)
} //运行结果
//0xc042052088 0xc0420461b0

指针的实际用法

变量、指针、地址,三者的关系?

  1.每个变量都拥有地址

  2.指针的值就是地址

  

如何使用指针获取指针指向的值?

  在对普通变量使用&操作符取地址获得这个变量的指针后,可以对指针使用*操作,也就是指针取值

package main
import (
"fmt"
)
func main() {
// 准备一个字符串类型
var house = "Malibu Point 10880, 90265"
// 对字符串取地址, 将指针保存到 ptr 中,ptr类型为*string
ptr := &house
// 打印ptr的类型 类型为 *string。
fmt.Printf("ptr type: %T\n", ptr)
// 打印ptr的指针地址 每次运行都会发生变化。
fmt.Printf("address: %p\n", ptr)
// 对 ptr 指针变量进行取值操作 value 变量类型为 string。
value := *ptr
// 取值后的类型
fmt.Printf("value type: %T\n", value)
// 指针取值后就是指向变量的值
fmt.Printf("value: %s\n", value)
} //运行结果
//ptr type: *string
//address: 0xc0420401b0
//value type: string
//value: Malibu Point 10880, 90265

指针获取指针

  取地址操作符&和取值操作符*是一对互补操作符

  &取出地址,*根据地址取出地址指向的值。

变量、指针地址、指针变量、取地址、取值的相互关系和特性:

  1.对变量进行取地址(&)操作,可以获得这个变量的指针变量。

  2.指针变量的值是指针地址。

  3.对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。

指针的零值和相等测试

  1.任何类型的指针的零值都是nil。

  2.如果 p != nil 为真,那么p就指向某个有效变量  (p为指针)

  3.指针只有指向同一个变量或者全部为nil时才相等。

var x,y int
var z *int
var w *string
fmt.Println(&x ==&x, &x ==&y,&x ==nil , z == nil , w ==nil) //true false false true true

指针的相等测试

如何使用指针修改值?

package main
import "fmt"
// 定义一个交换函数,参数为 a、b,类型都为 *int,都是指针类型。
func swap(a, b *int) {
// 将 a 指针取值,把值(int类型)赋给 t 变量,t 此时也是 int 类型。
t := *a
// 取 b 指针值,赋给 a 变量指向的变量。注意,此时*a的意思不是取 a 指针的值,而是“a指向的变量”。
*a = *b
// 将 t 的值赋给 b 指向的变量。
*b = t
}
func main() {
// 准备 x、y 两个变量,赋值 1 和 2,类型为 int。
x, y := 1, 2
// 取出 x 和 y 的地址作为参数传给 swap() 函数进行调用。
swap(&x, &y)
// 交换完毕时,输出 x 和 y 的值。
fmt.Println(x, y)
} //运行结果
//2 1

使用指针修改值

  1.*操作符作为右值时,意义是取指针的值

  2.作为左值时,也就是放在赋值操作符的左边时,表示 a 指向的变量。

  归纳:

    1.*操作符的根本意义就是操作指针指向的变量。

    2.当操作在右值时,就是取指向变量的值;

    3.当操作在左值时,就是将值设置给指向的变量。

  每次我们对一个变量取地址,或者是复制指针,我们都是为原变量创建新的别名。例如a就是变量p的别名。

  指针特别有价值的地方在于我们可以不用名字而访问一个变量的。  

package main
import "fmt"
func swap(a, b *int) {
b, a = a, b
}
func main() {
x, y := 1, 2
swap(&x, &y)
fmt.Println(x, y)
} //运行结果
//1 2

swap() 函数中交换指针值

  1.上面代码中的 swap() 函数交换的是 a 和 b 的地址

  2.在交换完毕后,a 和 b 的变量值确实被交换。

  3.但和 a、b 关联的两个变量并没有实际关联。

  4.这就像写有两座房子的卡片放在桌上一字摊开,交换两座房子的卡片后并不会对两座房子有任何影响。

创建指针的另一种方法--new()函数

package main

import "fmt"

func main() {
//申请一个指针str,类型为*string
str := new(string)
//指针str指向字符串“ninja”
*str = "ninja"
//打印str指向的地址空间
fmt.Println(*str)
//打印指针str的内存地址
fmt.Printf("%p\n",str)
fmt.Printf("%d\n",str)
//打印指针str的类型
fmt.Printf("%T\n",str) } //运行结果
//ninja
//0xc00000e1e0
//824633778656
//*string

new()方法创建指针

go语言的指针类型的更多相关文章

  1. 对于C语言复杂指针类型的分析

    转载自:http://www.slyar.com/blog/complicated-point-type.html int p; p是一个普通的整型变量. int *p; 1.p与*结合,说明p是一个 ...

  2. c语言定义指针类型需注意事项

    1)在定义说明语句中,指针变量名之前的星号“*“是指针变量的修饰符,也就是说它所修饰的变量是指针变量. 2)指针变量是用它们所指向的对象类型来区分的.如定义 int *ip,类型int并不是指针的类型 ...

  3. C语言之指针用法总结

    C语言指针概述:1.计算机系统中,无论是存入或是取出数据都需要与内存单元打交道,物理器件通过地址编码寻找内存单元.2.地址编码是一种数据,C语言的指针类型正是为了表示这种计算机所特有的地址数据.3.存 ...

  4. Swift中对C语言接口缓存的使用以及数组、字符串转为指针类型的方法

    由于Swift编程语言属于上层编程语言,而Swift中由于为了低层的高性能计算接口,所以往往需要C语言中的指针类型,由此,在Swift编程语言刚诞生的时候就有了UnsafePointer与Unsafe ...

  5. C语言之void类型及void指针 分类: C/C++ 2015-07-13 11:24 8人阅读 评论(0) 收藏

    原文网址:http://www.cnblogs.com/pengyingh/articles/2407267.html 1.概述 许多初学者对C/C 语言中的void及void指针类型不甚理解,因此在 ...

  6. C语言指针类型 强制转换

    关于C语言指针类型 强制转换  引用一篇文章: C语言中,任何一个变量都必须占有一个地址,而这个地址空间内的0-1代码就是这个变量的值.不同的数据类型占有的空间大小不一,但是他们都必须有个地址,而这个 ...

  7. Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型

    Android For JNI(五)--C语言多级指针,结构体,联合体,枚举,自定义类型 我们的C已经渐渐的步入正轨了,基础过去之后,就是我们的NDK和JNI实战了 一.多级指针 指针的概念我们在前面 ...

  8. C语言指针类型

    1:只要是指针类型,不管是几级指针[带几个*],其宽度都是4字节 2:任何数据类型[包括自己定义的结构体]前面都能加*号,表示该数据类型的一个指针 3:由于是386处理器,其数据处理的宽度都是四个字节 ...

  9. C语言 数组类型与数组指针类型

    //数组类型与数组指针类型 #include<stdio.h> #include<stdlib.h> #include<string.h> void main(){ ...

随机推荐

  1. (2)ASP.NET Core3.1 Ocelot路由

    1.路由 前一个章节我们已经介绍过Ocelot,相信大家也了解到,Ocelot的主要功能是接收客户端等传入的HTTP请求,并将其转发到下游服务.Ocelot当前仅以另一个http请求的形式支持此功能( ...

  2. 说说 C# 9 新特性的实际运用

    你一定会好奇:"老周,你去哪开飞机了?这么久没写博客了." 老周:"我买不起飞机,开了个铁矿,挖了一年半的石头.谁知铁矿垮了,压死了几条蜈蚣,什么也没挖着." ...

  3. 服务器断电导致的ORACLE异常 : ORA-00214 ORA-01033 ORA-01034 ORA-00172 ORA-27101

    工作环境中的集群迁移之后,oracle出了挺多问题,最开始一直没找到原因,后来发现做迁移的人是冷迁移的,且数据库节点是硬关机的,惊了( 表现症状有不能登陆,登录了不能操作等 第一个报的是 ORA-00 ...

  4. Flutter(75):Sliver组件之SliverFixedExtentList

    Flutter教学目录持续更新中 Github源代码持续更新中 1.SliverFixedExtentList 可以固定Item高度的SliverList 2.SliverFixedExtentLis ...

  5. 经典c程序100例 1-10

    ==1--10 [程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不 ...

  6. JS仿贪吃蛇:一串跟着鼠标的Div

    贪吃蛇是一款80后.90后比较熟悉的经典游戏,下面通过简单的JS代码来实现低仿版贪吃蛇效果:随着鼠标的移动,在页面中呈现所有Div块跟随鼠标依次移动,效果如下图所示. <!DOCTYPE htm ...

  7. linux全局和个人配置文件说明

    1.bash配置文件: 1).全局(bash的配置文件) 有 /etc/profile   /etc/profile.d/*  与 /etc/bashrc 其实都是bash这个程序启动的时候会读取配置 ...

  8. 《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”

    <Machine Learning in Action>-- Taoye给你讲讲决策树到底是支什么"鬼" 前面我们已经详细讲解了线性SVM以及SMO的初步优化过程,具体 ...

  9. rsync未授权访问漏洞复现

    rsync未授权访问漏洞简介 rsync是Linux/Unix下的一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件和目录,默认运行在873端口.由于配置不当,导致任何人可未授权访问r ...

  10. SQL注入学习-Dnslog盲注

    1.基础知识 1.DNS DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的 ...