Go语言核心36讲
郝林
《Go并发编程实战》作者,前轻松筹大数据负责人
立即订阅
24076 人已学习
课程目录
已完结 54 讲
0/4登录后,你可以任选4讲全文学习。
开篇词+学习路线 (3讲)
开篇词 | 跟着学,你也能成为Go语言高手
免费
预习篇 | 写给0基础入门的Go语言学习者
50 | 学习专栏的正确姿势
模块一:Go语言基础知识 (6讲)
01 | 工作区和GOPATH
02 | 命令源码文件
03 | 库源码文件
04 | 程序实体的那些事儿(上)
05 | 程序实体的那些事儿(中)
06 | 程序实体的那些事儿 (下)
模块二:Go语言进阶技术 (16讲)
07 | 数组和切片
08 | container包中的那些容器
09 | 字典的操作和约束
10 | 通道的基本操作
11 | 通道的高级玩法
12 | 使用函数的正确姿势
13 | 结构体及其方法的使用法门
14 | 接口类型的合理运用
15 | 关于指针的有限操作
16 | go语句及其执行规则(上)
17 | go语句及其执行规则(下)
18 | if语句、for语句和switch语句
19 | 错误处理(上)
20 | 错误处理 (下)
21 | panic函数、recover函数以及defer语句 (上)
22 | panic函数、recover函数以及defer语句(下)
模块三:Go语言实战与应用 (27讲)
23 | 测试的基本规则和流程 (上)
24 | 测试的基本规则和流程(下)
25 | 更多的测试手法
26 | sync.Mutex与sync.RWMutex
27 | 条件变量sync.Cond (上)
28 | 条件变量sync.Cond (下)
29 | 原子操作(上)
30 | 原子操作(下)
31 | sync.WaitGroup和sync.Once
32 | context.Context类型
33 | 临时对象池sync.Pool
34 | 并发安全字典sync.Map (上)
35 | 并发安全字典sync.Map (下)
36 | unicode与字符编码
37 | strings包与字符串操作
38 | bytes包与字节串操作(上)
39 | bytes包与字节串操作(下)
40 | io包中的接口和工具 (上)
41 | io包中的接口和工具 (下)
42 | bufio包中的数据类型 (上)
43 | bufio包中的数据类型(下)
44 | 使用os包中的API (上)
45 | 使用os包中的API (下)
46 | 访问网络服务
47 | 基于HTTP协议的网络服务
48 | 程序性能分析基础(上)
49 | 程序性能分析基础(下)
尾声与思考题答案 (2讲)
尾声 | 愿你披荆斩棘,所向无敌
新年彩蛋 | 完整版思考题答案
Go语言核心36讲
登录|注册

15 | 关于指针的有限操作

郝林 2018-09-14
在前面的文章中,我们已经提到过很多次“指针”了,你应该已经比较熟悉了。不过,我们那时大多指的是指针类型及其对应的指针值,今天我们讲的则是更为深入的内容。
让我们先来复习一下。
type Dog struct {
name string
}
func (dog *Dog) SetName(name string) {
dog.name = name
}
对于基本类型Dog来说,*Dog就是它的指针类型。而对于一个Dog类型,值不为nil的变量dog,取址表达式&dog的结果就是该变量的值(也就是基本值)的指针值。
如果一个方法的接收者是*Dog类型的,那么该方法就是基本类型Dog的指针方法。
在这种情况下,这个方法的接收者,实际上就是当前的基本值的指针值。
我们可以通过指针值无缝地访问到基本值包含的任何字段,以及调用与之关联的任何方法。这应该就是我们在编写 Go 程序的过程中,用得最频繁的“指针”了。
从传统意义上说,指针是一个指向某个确切的内存地址的值。这个内存地址可以是任何数据或代码的起始地址,比如,某个变量、某个字段或某个函数。
我们刚刚只提到了其中的一种情况,在 Go 语言中还有其他几样东西可以代表“指针”。其中最贴近传统意义的当属uintptr类型了。该类型实际上是一个数值类型,也是 Go 语言内建的数据类型之一。
根据当前计算机的计算架构的不同,它可以存储 32 位或 64 位的无符号整数,可以代表任何指针的位(bit)模式,也就是原始的内存地址。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Go语言核心36讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(23)

  • 郝林 置顶
    大家可以具体说说有哪些名词需要用示例解释?
    2019-06-03
    1
  • sun
    在描述不可寻址那部分有很多名词,要是能分别有段示例一下就好了,对照起来会更清晰
    2018-09-17
    36
  • 江山如画
    引用类型的指针值有意义。

    以切片为例:fmt.Printf("%p\n", sli) 和 fmt.Printf("%p\n", &sli[0]) 打印的都是底层数组元素的地址。
    而 fmt.Printf("%p\n", &sli) 打印的是切片结构体的内存地址,验证代码如下:

    arr := [3]int{1, 2, 3}
    fmt.Printf("%p\n", &arr) //0xc0000161e0

    sli := arr[:]
    fmt.Printf("%p\n", sli) //0xc0000161e0
    fmt.Printf("%p\n", &sli[0]) //0xc0000161e0

    fmt.Printf("%p\n", &sli) //0xc00000a080
    fmt.Println(unsafe.Pointer(&sli)) //0xc00000a080

    sliHeader := (*reflect.SliceHeader)(unsafe.Pointer(&sli))
    fmt.Printf("0x%10x\n", sliHeader.Data) //0xc0000161e0

    可以看到,使用 %p 打印地址的时候:&sli 和 unsafe.Pointer(&sli) 都指向了切片结构体的地址,&arr,sli ,&sli[0],sliHeader.Data 都指向了底层数组。
    2018-09-17
    1
    13
  • nuczzz
    get新技能: unsafe.Pointer+ uintptr突破私有成员访问!
    2018-11-16
    8
  • jacke
    字面量有人理解吗?求解释

    作者回复: 说白了就是用于表示值或者类型的代码段。比如:1234就是代表整数值的字面量,int64就是代表类型的字面量。很简单,不用想的太复杂。

    2018-10-13
    7
  • 公众号「后端进阶」
    既然知道dogPtr,那么必然也知道dogP的值,也就是可以通过dogP去那name的值了,不是很理解
    2018-09-14
    1
    6
  • 乖,摸摸头
    云里雾里,我在这里懵逼等你,我肯定懵逼的不只我一个
    2019-11-19
    2
  • Geek_a8be59
    根据您说的 由于 Go 语言中的字符串值也是不可变的
    var a = "123"
             var c = "123"
    fmt.Printf("a fist is %p\n",&a)
    a = "456"

    fmt.Printf("a two is %p \n",&a)
    b:=a
    fmt.Printf("a three is %p \n",&a)
    fmt.Printf("b is %p \n",&b)
    我想问的是
    ①这里的“123”和“456”值不可变,那是不是他们两个都是在常量区呢?我不清楚是不是有go有常量区这②如果字符串的值是不可变的,那么c和a的字符串的值的地址是一样的呢?
    ③那为什么&a != & c呢,这里是取的字面量a的地址么?是不是可以理解成*a才是真正字符串“123”的地址呢

    作者回复: 1. Go 语言没有常量区这个概念。
    2. 你要分清楚变量和值啊。变量本身的存储中包含了值,但不限于值。变量可以拥有或者代表一个值,但是它本身并不是值啊。
    3. 你无法获取值 "123" 和 "456" 本身的存储地址,因为 Go 语言规范规定这样的值本身是不可取址的。

    你可以参考 Go 运行时系统中对 string 结构的定义:

    type stringStruct struct {
    str unsafe.Pointer
    len int
    }

    这个声明所在文件的路径是:/src/runtime/string.go 。


    2019-07-02
    2
  • 猫王者
    go语言的引用类型本质还是结构体,包括切片,字典还有接口,底层都是用结构体来实现,引用类型的地址就是这个底层结构体的地址吧
    2018-10-09
    2
  • 高鸿祥
    动态语言过来的人表示看不懂😁
    2018-09-24
    2
  • 有铭
    C里的指针是用来直接操作内存的,因为C里有大量的操作是必须靠操作内存完成的。那么go这种带有GC,不需要手动分配内存的语言,指针存在的意义在哪里呢,Go里的指针在何时有“不得不使用”的意义呢?

    作者回复: 没有非得使用的必要。指针类型及其值最常用,因为可以达到传址的效果。

    2018-09-14
    1
    2
  • 引用类型的指针意义非常大,前边说过变量的赋值都是拷贝,是副本,对于结构体类型数据也是如此,你对一个结构体数据进行数据修改也是对副本进行修改,不会真的修改成功,但是要有引用就可以实现修改目的了
    2019-07-26
    1
  • 静水流深
    老师您好,引用类型的值的指针值,是否可以理解为指针的指针?

    作者回复: 你最好不要这么理解,否则会影响其他地方的理解。引用类型的值不是指针那么简单,它本身是有结构的,所以还是要按普通的值来理解,不要理解成指针。

    2019-07-18
    1
  • Laughing
    引用类型的值的指针,还是主要用于指针传递吧,比如做一些引用类型的复制?
    2018-10-05
    1
  • Michael
    “引用类型的值得指针值” 同C语言中 “指针的指针” 应该是一个概念;

    假设,有一个值类型 T,那么类型T的引用类型就是:*T,引用类型值得指针值类型就是:**T。

    var t = T{} // T
    var pt = &T // *T
    var ppt = &pt // **T

    但是具体的意义与使用场景还没想到,也没有遇到过,若老师不嫌弃,还请老师指出

    作者回复: 在Go需要中所谓的指针的指针最好不要用,Go也是想避免这种复杂性才搞出来引用类型的。

    2018-09-17
    1
  • Realm
    1 “引用类型的值的指针 ”与 “引用类型的值的值指针”是两个概念?

    2 值的值指针是类似切片、字典、通道内的元素的指针吗?

    如果是,那老师的思考题,引用类型的值的值指针的意义:是不是用此指针来取元素的值?

    作者回复: 我没说过“值指针”这个词。“引用类型的值的指针值”的含义你不理解还是?

    2018-09-14
    1
  • undifined
    老师 有一点没有理解,namePtr := dogPtr + unsafe.Offsetof(dogP.name)这里如果不知道这个属性是什么,怎么才能取到这个字段的便宜量呢

    作者回复: 不知道?不知道就没法取了。

    2018-09-14
    1
  • zerostarfro
    指针可以理解成内存里的软链接吗~ 如果a和b指向同一个指针,是不是改a同时也改b了

    作者回复: 这里说的指针值是经典的指针,保存的是某个内存地址,指针值变了就相当于指向的内存地址变了。我大概理解你的意思,答案是“不会改”。

    2019-11-28
  • 前面分类介绍那里,我感觉很绕,比如说,切片字面量的索引结果值,没看太懂,切片字面量是切片这个变量名称呢还是切片变量指向的值,索引结果值,是切片中索引指向的数据吗?还是这个索引本身的值呢?

    作者回复: 字面量,就是用来表示值本身的东西,比如:[]int32{1,2,3} 、"abc"等。索引结果值说全了是索引表达式的结果值,就是与给定的索引号对应的那个元素值。关于这些概念性名词,我记得都在文章里正面或侧面的解释过。如果你还有哪些不太明白,可以发评论问我。

    2019-08-15
  • 木凡
    var str string = "abc"
    fmt.Printf("str address %p \n", &str)
    打印出来的结果,是 str address 0xc0420461c0 ,我想问下,这个内存地址是变量str的内存地址么,或者说这个内存地址里面存储的内容是什么,是变量str,还是值abc

    作者回复: &str 取的是变量的存储地址。

    2019-07-12
收起评论
23
返回
顶部