go里面的指针用法
什么是指针
指针是存储一个变量的内存地址的变量。
在上图中,变量 b
的值是 156
,存储在地址为 0x1040a124
的内存中。变量 a
存储了变量 b
的地址。现在可以说 a
指向 b
。
指针的声明
指向类型 T
的指针用 *T
表示。
让我们写一些代码。
package main import (
"fmt"
) func main() {
b := 255
var a *int = &b
fmt.Printf("Type of a is %T\n", a)
fmt.Println("address of b is", a)
}
&
操作符用来获取一个变量的地址。在上面的程序中,第 9 行我们将 b
的地址赋给 a
(a
的类型为 *int
)。现在我们说 a
指向了 b
。当我们打印 a
的值时,b
的地址将会被打印出来。程序的输出为:
Type of a is *int
address of b is 0x1040a124
你可能得到的是一个不同的 b
的地址,因为 b
可以在内存中的任何地方。
指针的空值
指针的空值为 nil 。
package main import (
"fmt"
) func main() {
a := 25
var b *int
if b == nil {
fmt.Println("b is", b)
b = &a
fmt.Println("b after initialization is", b)
}
}
在上面的程序中,b
的初始值为 nil。接着将 a
的地址赋值给 b
。程序的输出为:
b is <nil>
b after initialisation is 0x1040a124
指针解引用
解引用指针的意思是通过指针访问被指向的值。指针 a
的解引用表示为:*a
。
让我们通过一个程序看一下它是怎么工作的。
package main
import (
"fmt"
) func main() {
b := 255
a := &b
fmt.Println("address of b is", a)
fmt.Println("value of b is", *a)
}
上面程序的第10行,我们将 a
解引用并打印这个解引用得到的值。和我们预期的一样,程序打印的是 b
的值。程序的输出为:
address of b is 0x1040a124
value of b is 255
让我们再写一个程序,该程序使用指针改变 b
的值。
package main import (
"fmt"
) func main() {
b := 255
a := &b
fmt.Println("address of b is", a)
fmt.Println("value of b is", *a)
*a++
fmt.Println("new value of b is", b)
}
在上面的程序中,我们将 a
指向的值自增 1,这样做也改变了 b
的值,因为 a
指向 b
。因此 b
的值变为 256
。程序的输出为:
address of b is 0x1040a124
value of b is 255
new value of b is 256
传递指针给函数
package main import (
"fmt"
) func change(val *int) {
*val = 55
}
func main() {
a := 58
fmt.Println("value of a before function call is",a)
b := &a
change(b)
fmt.Println("value of a after function call is", a)
}
在上面的程序中,第 14 行,我们将指向 a
的指针 b
传递给函数 change
。在函数 change
内部,第 8 行,通过解引用修改了 a
的值。程序的输出如下:
value of a before function call is 58
value of a after function call is 55
不要传递指向数组的指针给函数,而是使用切片
假设我们需要通过函数修改一个数组。一个办法是将数组的指针作为参数传递给函数。
package main import (
"fmt"
) func modify(arr *[3]int) {
(*arr)[0] = 90
} func main() {
a := [3]int{89, 90, 91}
modify(&a)
fmt.Println(a)
}
在上面的程序中,第13行,数组 a
的地址传递给了函数 modify
。在第8行的 modify
函数中,我们通过解引用的方式将数组的第一个元素赋值为 90
。程序输出为:[90 90 91]
。
a[x] 是 (*a)[x] 的简写,因此上面的程序中,(*arr)[0] 可以替换为 arr[0]。让我们用这种简写方式重写上面的程序:
package main import (
"fmt"
) func modify(arr *[3]int) {
arr[0] = 90
} func main() {
a := [3]int{89, 90, 91}
modify(&a)
fmt.Println(a)
}
程序的输出依然是:[90 90 91]
。
虽然可以通过传递数组指针给函数的方式来修改原始数组的值,但这在 Go 中不是惯用的方式,我们可以使用切片完成同样的事情。
让我们用切片的方式重写上面的程序:
package main import (
"fmt"
) func modify(sls []int) {
sls[0] = 90
} func main() {
a := [3]int{89, 90, 91}
modify(a[:])
fmt.Println(a)
}
在上面的程序中,第13行,我们传递了一个切片给 modify
函数。在函数内部,切片的第一个元素被修改为 90
。程序的输出为:[90 90 91]
。所以请不要以数组指针作为参数传递给函数,而是使用切片:)。这样的代码更加简洁,在 Go 中更常被使用。
Go 不支持指针运算
Go 不支持其他语言(比如C)中的指针运算。
package main func main() {
b := [...]int{109, 110, 111}
p := &b
p++
}
上面的程序将报错:main.go:6: invalid operation: p++ (non-numeric type *[3]int)
go里面的指针用法的更多相关文章
- Leetcode刷题之矩阵中的指针用法
矩阵中的指针用法 1 快慢指针 Leetcode27移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度.不要使用额外的数组 ...
- C# this指针用法
this指针是什么: 这里有一些面向对象编程的概念需要说明:类(Class)的概念和对象(Object)的概念类是对事物概括,也是C#编码时所有代码归属的基本单位:而对象是对类的实例化,也就是C#里n ...
- c++ 智能指针用法详解
本文介绍c++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被c++11弃用. 为什么要使用智能 ...
- C和C指针小记(九)-指针用法1
1. *p++ 最常用的一个指针的用法,就是在循环中用来迭代. *p++ 共有3步操作: 1.++操作符把p所指向的内存中的值复制一份 2.++操作符把p加1(实际是一个p所指内存单元的大小,这也是编 ...
- typedef函数指针用法
typedef void(*vp)(); 将vp声明为一个函数指针类型,该类型的指可以针指向一个没有参数,带空返回值的函数. 调用方法vp p;创建一个vp类型的函数指针p void print(vp ...
- c语言指针用法
一.指针 int t 定义整型变量 int *p p为指向整型数据的指针变量 int a[n] 定义整型数组a,它有n个元素 int *p[n] 定义指针数组p,它由n个指向整形数据的指针元素组成 i ...
- C++中const指针用法汇总
这里以int类型为例,进行说明,在C++中const是类型修饰符: int a; 定义一个普通的int类型变量a,可对此变量的值进行修改. const int a = 3;与 int const a ...
- C语言的指针用法:输入一堆字符,把非字母的删去。
char *p,a[20]; int i; gets(a); //这个语句不同于getchar(),后者只能一次输入一个,而前者可以一次输完所有的字符!!! p=a; //这个语句 ...
- C语言之指针用法总结
C语言指针概述:1.计算机系统中,无论是存入或是取出数据都需要与内存单元打交道,物理器件通过地址编码寻找内存单元.2.地址编码是一种数据,C语言的指针类型正是为了表示这种计算机所特有的地址数据.3.存 ...
随机推荐
- jsp页面时间戳转换为时间格式
jstl中格式化时间戳 在jsp页面中使用jstl标签将long型的时间戳转换为格式化后的时间字符串 1.通过<jsp:useBean /> 导入java.util.Date类2.通过 ...
- jackson 用法总结
1.序列化与反序列化封装 private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class); /** * Obj ...
- C#常用工具类——Excel操作类(ZT)
本文转载于: http://www.cnblogs.com/zfanlong1314/p/3916047.html /// 常用工具类——Excel操作类 /// <para> ----- ...
- Dubbo 源码分析 - 集群容错之 LoadBalance
1.简介 LoadBalance 中文意思为负载均衡,它的职责是将网络请求,或者其他形式的负载"均摊"到不同的机器上.避免集群中部分服务器压力过大,而另一些服务器比较空闲的情况.通 ...
- git添加远程仓库
3种方式 # 未创建项目目录git clone https://github.com/xxx/zzz.git [这里指定目标文件夹,不填写,默认创建 zzz目录] # 已存在项目文件,未设置远程仓库的 ...
- PHP的会话控制
页面数据的作用域: 当前页共享数据:变量.常量 两个页面间传递数据:get,post 跟踪用户的多页面数据共享(会话):session.cookie 全局数据共享:文件.数据库.memcached C ...
- Hashtable 为什么不叫 HashTable?
前几天在写<HashMap 和 Hashtable 的 6 个区别>这篇文章的时候,差点把 Hashtable 写成了 HashTable,后来看源码证实了是:Hashtable,小写的 ...
- 访问iis出现500.21错误
上图是错误的界面 刚开始接手了一个项目,然后想发布到iis上访问使用效果,结果出现了上面的问题,最开始以为是 .net Framework版本的问题,每个版本都试过了,结果问题并没有完全解决. 下面 ...
- 异步请求中jetty处理ServletRequestListener的坑
标题起得比较诡异,其实并不是坑,而是jetty似乎压根就没做对异步request的ServletRequestListener的特殊处理,如果文中有错误欢迎提出,可能自己有所疏漏了. 之前遇到了一个b ...
- odoo开发笔记 -- div标签代替odoo button写法
odoo开发笔记 -- div标签代替odoo button写法 并调用自定义js <footer> <div id="confirm_request_cloud_repo ...