Go起步:5、复合类型2--指针(pointer)、结构体(struct)
2016-08-29 19:49
344 查看
之前关于Go的复合类型聊到数组和切片,今天继续看看指针(pointer)和结构体(struct)。
我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。
这里先要说下Go语言的取地址符– &,放到一个变量前使用就会返回相应变量的内存地址。
%x是十六进制输出。
可以看出,两次运行的结果中,int型的变量地址不同的,string型的变量地址是相同的,这点是不是和java一样呢?–int是值类型,string是引用类型。
以上定义了一个int类型的指针。
& 操作符会生成一个指向其操作数的指针。
* 操作符表示指针指向的底层值。
可以看出,
指正定义是默认的地址是0,这时它的值就是nil。
当指针指向变量i时,它的地址就变成了变量i的地址,通过&操作符完成,这时他的值就是变量i的值。
当通过操作符*改变指针的值时,对应的i的值也发生了变化,以为他们引用的是同一个地址上的值。
这也就是通常所说的“间接引用”或“重定向”。
总结一下,使用指针需要三步,首先,定义指针变量。然后,为指针变量赋值(&)。最后就可以访问指针变量中指向地址的值(*)。
声明格式如下:
以上指向指针的指针变量为整型。
可以看出,变量a,ptr,pptr都指向了同一个地址。实际上他们引用的是同一个内存地址,所以他们的值也都是一样的。
总之,指针在Go中的用途还是很广泛的,大部分同C语言的也有些共通指出,但与 C 不同,Go 没有指针运算。
如下的代码:
上面的代码定义了一个名为Vertex的结构体,结构体是由int和string两个数据类型构成。
然后在main函数中定义了一个类型为Vertex的变量。通过上面的程序也可以得出,操作一个结构体的内容直接通过.操作符就可以了,不管是取值还是赋值。
特殊的前缀 & 返回一个指向结构体的指针。
如果我们有一个指向结构体的指针 p ,那么可以通过 (*p).X 来访问其字段 X 。 不过这么写太啰嗦了,所以语言也允许我们使用隐式间接引用,直接写 p.X 就可以。
可以看出,定义的指向结构体v的指针p,对于p的修改就是修改了之前的结构体v。
指针(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。
相关文章推荐
- Go起步:4、复合类型1--数组array和切片slice
- [Go] 复合类型(数组、切片、字典、结构体)变量的 初始化 及 注意事项
- C++的数组、结构体、指针三种复合类型知识点小总结
- Go起步:6、复合类型3--字典(map)及其他
- Go基础编程:复合类型—指针
- C# 之 结构体(struct)---复合类型的数据结构
- Go基础编程:复合类型—结构体
- 结构体struct的应用、结构体变量、结构体指针变量、结构体指针变量类型的区别
- C语言中不同类型的结构体的指针间可以强制转换
- struct 结构体中 数组和指针
- 关于stl::vector中存储带指针类型成员的结构体指针
- 关于struct,union,enum三大复合数据类型
- 《coredump问题原理探究》Linux x86版5.6节C风格数据结构内存布局之复合类型构成的结构体
- 复合数据类型,结构体,联合,枚举
- go - struct类型
- typedef 还可以掩饰复合类型,如指针和数组
- 1.0 基础、标示符、常量、数据类型(enum 枚举,struct 结构体)、操作符、循环、数组
- nsvalue与结构体,指针和一些基本类型互转
- GO系列之struct类型
- c# 结构体struct包含数与byte类型的转换(二)