Golang入门教程(十五)指针
什么是指针?
指针是一个变量,用于存储另一个变量的内存地址。

在上面的例子中,变量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)
}
&运算符用于获取变量的地址。 在上面的程序中,我们将b的地址赋给一个类型为* int的类型。 据说现在a指向b。 当我们在a中打印该值时,b的地址将被打印。 这个程序输出
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_01.go"
Type of a is *int
address of b is 0xc042054080
你可能会得到一个不同的b地址,因为b的位置可以在内存中的任何地方。执行两次得到的结果
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_01.go"
Type of a is *int
address of b is 0xc042054080 [Done] exited with code=0 in 11.167 seconds [Running] go run "d:\GoProject\src\golang-study-line\basic-02\tempCodeRunnerFile.go"
Type of a is *int
address of b is 0xc04200e098 [Done] exited with code=0 in 0.954 seconds
空指针
指针的零值为 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的地址。 这个程序输出(同样是执行两次):
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_02.go"
b is <nil>
b after initialization is 0xc042054080 [Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_02.go"
b is <nil>
b after initialization is 0xc042054080
如何引用一个指针
如何引用指针意味着访问指针指向的变量的值。 * 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行中,我们引用并打印它的值。 如预期的那样,它打印出b的值。 该程序的输出是
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_03.go"
address of b is 0xc042054080
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.程序的输出是
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_04.go"
address of b is 0xc04200e098
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)
}
在上面的程序中,在第4行号。 我们将指针变量b传递给函数改变。 内部转换函数中,使用第8行中的解除引用来更改a的值。该程序输出,
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_05.go"
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)
}
在上面的程序中的第3行号,我们将数组a的地址传递给修改函数。 在修改函数的第8行中,我们取消引用arr并将90分配给数组的第一个元素。 这个程序输出
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\tempCodeRunnerFile.go"
[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)
}
这个程序也输出
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_07.go"
[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行中,我们将一个切片传递给修改函数。 切片的第一个元素在修改函数中更改为90。
这个程序输出
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_08.go"
[90 90 91]
所以避免传递指向数组的指针,使用切片代替它。 这段代码更干净并且是惯用的Go
Go不支持指针算术
Go不支持C语言等其他语言中的指针运算。
package main
func main() {
b := [...]int{109, 110, 111}
p := &b
p++
}
上面的程序会抛出编译错误
[Running] go run "d:\GoProject\src\golang-study-line\basic-02\basic_pointer_09.go"
# command-line-arguments
basic-02\basic_pointer_09.go:6:6: invalid operation: p++ (non-numeric type *[3]int)
参考:
https://golangbot.com/pointers/
Golang入门教程(十五)指针的更多相关文章
- 无废话ExtJs 入门教程十五[员工信息表Demo:AddUser]
无废话ExtJs 入门教程十五[员工信息表Demo:AddUser] extjs技术交流,欢迎加群(201926085) 前面我们共介绍过10种表单组件,这些组件是我们在开发过程中最经常用到的,所以一 ...
- RabbitMQ入门教程(十五):普通集群和镜像集群
原文:RabbitMQ入门教程(十五):普通集群和镜像集群 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.c ...
- SpringBoot入门教程(十五)集成Druid
Druid是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0.DBCP.PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB ...
- Photoshop入门教程(五):滤镜
学习心得:滤镜通常用于摄影行业,是安装在相机镜头前用于过滤自然光的附加镜头,从而获得一些特殊的效果.同理,Photoshop的滤镜也是为了产生特殊的效果.Photoshop滤镜分为两类:一种是内部滤镜 ...
- RabbitMQ入门教程(十六):RabbitMQ与Spring集成
原文:RabbitMQ入门教程(十六):RabbitMQ与Spring集成 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https: ...
- WCF入门教程(五)配置文件
WCF入门教程(五)配置文件 服务协定以及实现写好后,需要将相关服务公布出去,就需要HOST来承载,供客户端来调用. 承载服务有两种方式,一种通过配置文件,一种通过代码进行配置.上一章已经介绍了代码方 ...
- 无废话ExtJs 入门教程十九[API的使用]
无废话ExtJs 入门教程十九[API的使用] extjs技术交流,欢迎加群(201926085) 首先解释什么是 API 来自百度百科的官方解释:API(Application Programmin ...
- Docker入门教程(五)Docker安全
Docker入门教程(五)Docker安全 [编者的话]DockOne组织翻译了Flux7的Docker入门教程,本文是系列入门教程的第五篇,介绍了Docker的安全问题,依然是老话重谈,入门者可以通 ...
- 无废话ExtJs 入门教程十六[页面布局:Layout]
无废话ExtJs 入门教程十六[页面布局:Layout] extjs技术交流,欢迎加群(201926085) 首先解释什么是布局: 来自百度词典的官方解释:◎ 布局 bùjú: [distributi ...
- 无废话ExtJs 入门教程十四[文本编辑器:Editor]
无废话ExtJs 入门教程十四[文本编辑器:Editor] extjs技术交流,欢迎加群(201926085) ExtJs自带的编辑器没有图片上传的功能,大部分时候能够满足我们的需要. 但有时候这个功 ...
随机推荐
- linux tar 解压命令
如果提示 common not find 先进行安装如下 wget http://www.rarsoft.com/rar/rarlinux-5.3.0.tar.gz tar -zxvf rarlinu ...
- BZOJ 4833: [Lydsy1704月赛]最小公倍佩尔数(数论 + 最值反演)
题面 令 \({(1+\sqrt 2)}^n=e(n)+f(n)*\sqrt2\) ,其中 \(e(n),f(n)\) 都是整数,显然有 \({(1-\sqrt 2)}^n=e(n)-f(n)*\sq ...
- 文艺平衡Splay树学习笔记(2)
本blog会讲一些简单的Splay的应用,包括但不局限于 1. Splay 维护数组下标,支持区间reserve操作,解决区间问题 2. Splay 的启发式合并(按元素多少合并) 3. 线段树+Sp ...
- [luogu3391][bzoj3223]文艺平衡树【splay】
题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 分析 ...
- <Android基础>(三) UI开发 Part 1
1.常用控件 1)TextView 2)Button 3)EditText 4)ImageView 5)ProgressBar 6)AlertDialog 7)ProgressDialog 2.四种布 ...
- 实验八 应用层协议Ⅱ-FTP协议分析
实验八 应用层协议Ⅱ-FTP协议分析 一.实验目的 1.掌握FTP协议的实现原理. 2.了解控制通道和数据通道. 二.实验内容 用WareShark追踪ftp连接. 1.三次握手 2.ftp服务器回发 ...
- 「TJOI2015」组合数学 解题报告
「TJOI2015」组合数学 这不是个贪心吗? 怎么都最小链覆盖=最大点独立集去了 注意到一个点出度最多只有2,可以贪心一下出度的去向 按读入顺序处理就可以,维护一个\(res_i\)数组,表示上一行 ...
- codeforces #530 D(Sum in the tree) (树上贪心)
Mitya has a rooted tree with nn vertices indexed from 11 to nn, where the root has index 11. Each ve ...
- js 判断字符串中是否包含某个字符串
String对象的方法 方法一: indexOf() (推荐) var str = "123"; console.log(str.indexOf("3") ...
- js click 与 onclick 事件绑定,触发与解绑
click 与 onclick 1.onclick 事件会在对象被点击时发生. <input id="btn1" type="button" onclic ...