golang 指针的知识点

读书笔记https://go101.org/article/pointer.html

尽管golang吸收了很多其它语言的特点,但是go还是算是C家庭的语言。指针就是其中的一个证据。Go的指针与C指针有相同的地方也有不同的地方。

什么是指针

Go中有一个叫Pointer的类型。

Go Pointer类型与值

类型T的指针可以表示为*T。

关于什么是non-defined pointer和defined pointer

*int  // A non-defined pointer type whose base type is int.
**int // A non-defined pointer type whose base type is *int.
​
// Ptr is a defined pointer type whose base type is int.
type Ptr *int
// PP is a defined pointer type whose base type is Ptr.
type PP *Ptr

显然non-defined pointer具有更好的可读性。

关于引用

指针的值引用了其它值。

有两种方式取到non-nil指针:

  1. 关键字new,用得比较少。

  2. 取地址&。

pointer Dereference

也就是取指针的值 *p

如果p为nil,运行时会panic

package main
​
import "fmt"
​
func main() {
    p0 := new(int)   // p0 points to a zero int value.
    fmt.Println(p0)  // (a hex address string)
    fmt.Println(*p0) // 0
​
    // x is a copy of the value at
    // the address stored in p0.
    x := *p0
    // Both take the address of x.
    // x, *p1 and *p2 represent the same value.
    p1, p2 := &x, &x
    fmt.Println(p1 == p2) // true
    fmt.Println(p0 == p1) // false
    p3 := &*p0 // <=> p3 := &(*p0) <=> p3 := p0
    // Now, p3 and p0 store the same address.
    fmt.Println(p0 == p3) // true
    *p0, *p1 = 123, 789
    fmt.Println(*p2, x, *p3) // 789 789 123
​
    fmt.Printf("%T, %T \n", *p0, x) // int, int
    fmt.Printf("%T, %T \n", p0, p1) // *int, *int
}

为什么需要指针

go中所有值的赋值都是值拷贝,包括函数参数传递。

package main
​
import "fmt"
​
func double(x *int) {
    *x += *x
    x = nil // the line is just for explanation purpose
}
​
func main() {
    var a = 3
    double(&a)
    fmt.Println(a) // 6
    p := &a
    double(p)
    fmt.Println(a, p == nil) // 12 false
}

可以返回局部变量的指针,并且是安全的

//这样是允许的
func newInt() *int {
    a := 3
    return &a
}

指针的限制

Go指针值不支持算术运算

p++, p-2是非法的,主要为了安全。

*p++其实是(*p)++,不算指针的运算

指针值不能转换为任意指针类型

两个类型T1、T2的指针值能转换的前提是:

  1. T1和T2的底层类型是相同的(忽略struct tags),特别是如果T1,T2是non-define类型并且底层类型是相同的(考虑struct tags),然后转换是隐式的。

  2. 如果T1和T2都是non-defined类型,并且底层类型是相同的(忽略struct tags)。

type MyInt int64
type Ta    *int64
type Tb    *MyInt
  1. *int64 可以隐含地转换为Ta,反之也行。

  2. *MyInt 可以隐含地转换为Tb,反之也行。

  3. *MyInt 可以显性地转换为 *int64,反之也行。

  4. Ta不能直接转换成Tb,显式也不行。需要

    Tb((*MyInt)((*int64)(pa)))

指针值不能和任意指针比较

只有类型相同的指针(或可以进行隐式转换的)才能用==和!=比较,还有nil。

不同类型的指针不能相互赋值

打破上面的限制

使用包unsafe。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FatherOfCodingMan

如果觉得有用的话,可以赏点饭钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值