Golang教程:指针
什么是指针
指针是存储一个变量的内存地址的变量。
在上图中,变量 b
的值是 156
,存储在地址为 0x1040a124
的内存中。变量 a
存储了变量 b
的地址。现在可以说 a
指向b
。
指针的声明
一个指针变量指向了一个值的内存地址。
类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下:
var var_name *var-type
var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。以下是有效的指针声明:
var ip *int /* 指向整型*/
var fp *float32 /* 指向浮点型 */
让我们写一些代码。
package main import (
"fmt"
) func main() {
b :=
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 :=
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 :=
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
让我们再写一个程序,该程序使用指针改变 b
的值。
package main import (
"fmt"
) func main() {
b :=
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
new value of b is
传递指针给函数
package main import (
"fmt"
) func change(val *int) {
*val =
}
func main() {
a :=
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
value of a after function call is
不要传递指向数组的指针给函数,而是使用切片
假设我们需要通过函数修改一个数组。一个办法是将数组的指针作为参数传递给函数。
package main import (
"fmt"
) func modify(arr *[]int) {
(*arr)[] =
} func main() {
a := []int{, , }
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 *[]int) {
arr[] =
} func main() {
a := []int{, , }
modify(&a)
fmt.Println(a)
}
程序的输出依然是:[90 90 91]
。
虽然可以通过传递数组指针给函数的方式来修改原始数组的值,但这在 Go 中不是惯用的方式,我们可以使用切片完成同样的事情。
让我们用切片的方式重写上面的程序:
package main import (
"fmt"
) func modify(sls []int) {
sls[] =
} func main() {
a := []int{, , }
modify(a[:])
fmt.Println(a)
}
在上面的程序中,第13行,我们传递了一个切片给 modify
函数。在函数内部,切片的第一个元素被修改为 90
。程序的输出为:[90 90 91]
。所以请不要以数组指针作为参数传递给函数,而是使用切片:)。这样的代码更加简洁,在 Go 中更常被使用。
Go 不支持指针运算
Go 不支持其他语言(比如C)中的指针运算。
package main func main() {
b := [...]int{, , }
p := &b
p++
}
上面的程序将报错:main.go:6: invalid operation: p++ (non-numeric type *[3]int)
Golang教程:指针的更多相关文章
- Golang教程:数组和切片
数组 数组是类型相同的元素的集合.例如,整数 5, 8, 9, 79, 76 的集合就构成了一个数组.Go不允许在数组中混合使用不同类型的元素(比如整数和字符串). 声明 var variable_n ...
- Golang教程:变量
声明单一变量 声明一个变量的语法为:var name type,例如 package main import "fmt" func main() { var age int // ...
- 手把手golang教程【二】——数组与切片
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第五篇,这一篇我们将会了解golang中的数组和切片的使用. 数组与切片 golang当中数组和C++中的定义类似, ...
- golang:指针理解总结
指针的定义 指针是一个代表着某个内存地址的值.这个内存地址往往是在内存中存储的另一个变量的值的起始位置. go指针是提供操作数据的基本桥梁.因为go很多调用,往往复制一份对象,例如函数的参数,如果没有 ...
- Golang之指针(point)再探索
先记录代码 package main import "fmt" /* 声明指针 *T 是指向类型T的值的指针变量的类型 */ func main() { //b := 255 // ...
- golang之指针
先上代码 package main import "fmt" type myInt int //匿名函数 //值的接收 //指针的接收 //*myint表示myInt的指针类型 / ...
- [Objective-C语言教程]指针(15)
Objective-C中的指针简单易学.使用指针可以更轻松地执行某些Objective-C编程任务,并且在不使用指针的情况下无法执行其他任务(如动态内存分配). 所以有必要学习指向成为一个完美的Obj ...
- golang的指针和切片
首先为什么要讲go的指针和切片放在一起? 因为go指针和切片都是引用类型 引用类型就是说切片和指针保存的只是内存的地址,而不是具体的值,效率在大数据读取方面效率会高很多. 1.怎么定义一个切片 方法1 ...
- Golang教程:结构体
结构体(struct)是用户自定义的类型,它代表若干字段的集合.有些时候将多个数据看做一个整体要比单独使用这些数据更有意义,这种情况下就适合使用结构体. 比如将一个员工的 firstName, las ...
随机推荐
- [NetCore学习记录]第一章.使用netcore撸个简单的增删改查
1.引言 2.解决方案各部分介绍图 3.添加数据模型 4.添加数据库上下文 5.修改配置文件 6.使用依赖关系注入容器注册数据库上下文 7.添加基架工具并执行初始迁移 1.引言 NetCore出来有一 ...
- MicroPython (一)点亮我的Led
工具 : putty F429Discovery 开发板 Notepad++ 注意:不知道为什么 其他的终端工具有问题,推荐 putty 基本没有发现问题 putty 实时调试 使用putty 打开U ...
- 项目前端打包工具从 NEJ 切换成 webpack
此文已由作者张磊授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 这里不讨论 NEJ 和 webpack 的优劣,仅从技术角度来探寻一下能否实现,以及实现的代价. 前言 上一篇 ...
- WebStrom创建自定义后缀名的文件
如下图所示,我在下面的项目里面创建了.ejs文件,但是正常的情况下我们WebStrom是无法创建.ejs文件的,那么我们怎么才能让我们的WebStrom拥有创建该后缀名的文件的能力呢? 不BB,直接看 ...
- php swoole扩展安装
一波三折. 首先下载swoole安装包(由于我这里php是7,所以说应该去官网下载最新的swoole包,否则会发生意想不到的错误) wget https://github.com/swoole/swo ...
- python IDE安装-mac
mac 配置Python集成开发环境(Eclipse +Python+Pydev) 1.下载Mac版64位的Eclipse. 进入到Eclipse官方网站的下载页面(http://www.ecli ...
- Ubuntu16.04实用python脚本 - JDK的配置!
前提已经把Oracle JDK解压缩到指定目录了,我的JDK目录是:“/usr/jdk1.8.0_121” 全部脚本: # coding=utf-8 ,中文注释需要加入编码格式 #这是我的测试文件,在 ...
- Elasticsearch学习(1) Spring boot整合Elasticsearch
本文的Spring Boot版本为1.5.9,Elasticsearch版本为2.4.4,话不多说,直接上代码. 一.启动Elasticsearch 在官网上下载Elasticsearch后,打开bi ...
- Determining the Size of a Class Object---sizeof(class)---By Girish Shetty
There are many factors that decide the size of an object of a class in C++. These factors are: Size ...
- P2540 斗地主增强版
P2540斗地主增强版 参考大佬题解 思路:顺子暴力搜,剩下的牌我不会贪心所以用记忆化搜索(或者dp): 注意:双王不能当对,二不算顺子 代码 #include <cstdio> #inc ...