Go起步:5、复合类型2--指针(pointer)、结构体(struct)

之前关于Go的复合类型聊到数组和切片,今天继续看看指针(pointer)和结构体(struct)。

指针(pointer)

取地址符–&

Go具有指针。指针保存了变量的内存地址。
我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。
这里先要说下Go语言的取地址符– &,放到一个变量前使用就会返回相应变量的内存地址。

package main

import "fmt"

func main() {
    var a int = 20
    var s string = "a"

    fmt.Printf("a 变量的存储地址: %x\n", &a)
    fmt.Printf("s 变量的存储地址: %x\n", &s)
}

%x是十六进制输出。
这里写图片描述
这里写图片描述

可以看出,两次运行的结果中,int型的变量地址不同的,string型的变量地址是相同的,这点是不是和java一样呢?–int是值类型,string是引用类型。

指针的定义

类型 *T 是指向 T 类型值的指针。其零值为 nil 。

var p *int

以上定义了一个int类型的指针。
& 操作符会生成一个指向其操作数的指针。
* 操作符表示指针指向的底层值。

package main

import "fmt"

func main() {
    var p *int //定义一个指针变量
    fmt.Printf("p 变量的初始存储地址: %x\n", p)

    i := 10
    p = &i //将指针指向变量i

    fmt.Printf("p 变量的存储地址: %x\n", p)
    /* 使用指针访问值 */
    fmt.Printf("*p 变量的值: %d\n", *p)
    fmt.Printf("i 变量的值: %d\n", i)
    *p = 20 //通过指针 p 设置 i
    fmt.Printf("p 变量的存储地址: %x\n", p)
    /* 使用指针访问值 */
    fmt.Printf("*p 变量的值: %d\n", *p)
    fmt.Printf("i 变量的值: %d\n", i)
}

这里写图片描述
可以看出,

  • 指正定义是默认的地址是0,这时它的值就是nil。
  • 当指针指向变量i时,它的地址就变成了变量i的地址,通过&操作符完成,这时他的值就是变量i的值。
  • 当通过操作符*改变指针的值时,对应的i的值也发生了变化,以为他们引用的是同一个地址上的值。
    这也就是通常所说的“间接引用”或“重定向”。
    总结一下,使用指针需要三步,首先,定义指针变量。然后,为指针变量赋值(&)。最后就可以访问指针变量中指向地址的值(*)。

指针的指针

如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址。
这里写图片描述
声明格式如下:

var ptr **int;

以上指向指针的指针变量为整型。

package main

import "fmt"

func main() {

    var a int
    var ptr *int
    var pptr **int

    a = 10

    /* 指针 ptr 地址 */
    ptr = &a

    /* 指向指针 ptr 地址 */
    pptr = &ptr

    /* 获取 pptr 的值 */
    fmt.Printf("变量 a = %d\n", a)
    fmt.Printf("变量 a 内存地址 %x\n", &a)
    fmt.Printf("指针变量 *ptr = %d\n", *ptr)
    fmt.Printf("指针变量 *ptr 内存地址 %x\n", &*ptr)
    fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
    fmt.Printf("指向指针的指针变量 **pptr 内存地址 %x\n", &**pptr)
}

这里写图片描述
可以看出,变量a,ptr,pptr都指向了同一个地址。实际上他们引用的是同一个内存地址,所以他们的值也都是一样的。
总之,指针在Go中的用途还是很广泛的,大部分同C语言的也有些共通指出,但与 C 不同,Go 没有指针运算。

结构体(struct)

结构体( struct )就是由一系列具有相同类型或不同类型的数据构成的字段集合。在结构体中可以为不同项定义不同的数据类型。

定义和初始化

struct关键之用于定义结构体,type 声明就是定义的类型。

type T struct {
    name string // name of the object
    value int // its value
}

如下的代码:

package main

import "fmt"

type Vertex struct {
    X int
    Y string
}

func main() {
    var v = Vertex{1, "s"}
    fmt.Println(v)
    fmt.Println(v.X)
    fmt.Println(v.Y)
    v.X = 10
    fmt.Println(v.X)
}

这里写图片描述
上面的代码定义了一个名为Vertex的结构体,结构体是由int和string两个数据类型构成。
然后在main函数中定义了一个类型为Vertex的变量。通过上面的程序也可以得出,操作一个结构体的内容直接通过.操作符就可以了,不管是取值还是赋值。

结构体指针

结构体指针就是指向结构体的指针,类似于其他指针变量。定义结构体指针,结构体的字段就可以通过结构体指针来访问。
特殊的前缀 & 返回一个指向结构体的指针。
如果我们有一个指向结构体的指针 p ,那么可以通过 (*p).X 来访问其字段 X 。 不过这么写太啰嗦了,所以语言也允许我们使用隐式间接引用,直接写 p.X 就可以。

package main

import "fmt"

type Vertex struct {
    X int
    Y string
}

func main() {
    v := Vertex{1, "2"}
    p := &v
    p.X = 333333333
    fmt.Println(v)
    fmt.Println(p.X)
    fmt.Println((*p).X)
}

这里写图片描述
可以看出,定义的指向结构体v的指针p,对于p的修改就是修改了之前的结构体v。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值