1.指针
概念:存放数据的内存地址
func main() {
a := 10
fmt.Printf("a的地址是:%p\n", &a)
/*定义指针*/
var p1 *int
fmt.Println(p1)
p1 = &a
fmt.Println("p1的数值为:", p1)
fmt.Printf("p1的地址是:%p\n", &p1)
fmt.Println("p1指向的数值为:", *p1)
a = 100
fmt.Printf("a的地址是:%p\n", &a)
*p1 = 150
fmt.Printf("a的地址是:%p,值为:%d\n", &a, *p1)
/*指针的指针*/
var p2 **int
p2 = &p1
fmt.Println("p2的数值为:", p2)
fmt.Printf("p2的地址是:%p\n", &p2)
fmt.Printf("p2--->a:%d\n", **p2)
}
/*result
a的地址是:0xc0000b6010
<nil>
p1的数值为: 0xc0000b6010
p1的地址是:0xc0000ba020
p1指向的数值为: 10
a的地址是:0xc0000b6010
a的地址是:0xc0000b6010,值为:150
p2的数值为: 0xc0000ba020
p2的地址是:0xc0000ba028
p2--->a:150
*/
2.数组指针与指针数组
数组指针:首先是一个数组,由指针指向该数组的地址
指针数组:数组当中存放的数据类型是指针
/*数组指针与指针数组*/
fmt.Println("数组指针与指针数组")
//数组指针
arr1 := [3]int{1, 1, 1}
var pp1 *[3]int
pp1 = &arr1
fmt.Println("数组指针pp1指向数组arr1")
fmt.Println("数组指针pp1的数值为:", pp1)
fmt.Printf("数组指针pp1的数值为:%p\n", pp1)
fmt.Printf("数组指针pp1的地址为:%p\n", &pp1)
fmt.Println("数组指针pp1所指向的数组的数值为:", *pp1)
(*pp1)[0] = 100 //记得加括号
//pp1[0] = 100//简化写法
fmt.Println("数组指针pp1所指向的数组的数值为:", *pp1)
fmt.Println("数组arr1为:", arr1)
//指针数组
q, w, e := 7, 8, 9
arr2 := [3]*int{&q, &w, &e}
fmt.Println(arr2)
fmt.Printf("%T\n", arr2)
fmt.Println(*arr2[0], *arr2[1], *arr2[2])
q = 111
fmt.Println(*arr2[0], *arr2[1], *arr2[2])
fmt.Println(arr2)
*arr2[0] = 159
fmt.Println(*arr2[0], *arr2[1], *arr2[2])
fmt.Println(arr2)
/*result
数组指针与指针数组
数组指针pp1指向数组arr1
数组指针pp1的数值为: &[1 1 1]
数组指针pp1的数值为:0xc0000b8040
数组指针pp1的地址为:0xc0000ba030
数组指针pp1所指向的数组的数值为: [1 1 1]
数组指针pp1所指向的数组的数值为: [100 1 1]
数组arr1为: [100 1 1]
[0xc0000b6058 0xc0000b6060 0xc0000b6068]
[3]*int
7 8 9
111 8 9
[0xc0000b6058 0xc0000b6060 0xc0000b6068]
159 8 9
[0xc0000b6058 0xc0000b6060 0xc0000b6068]
*/
同理还有函数指针与指针函数,道理与上述类似。
另外,在将指针作为函数的参数传递时需要注意,指针作为参数传递其类型是引用传递。
3.结构体
概念:结构体是由一系列相同类型或者不同数据类型组成的数据集合。(之前提到的数组仅仅由相同类型组成)
语法:
type structName struct{
memberName type
memberName type
......
}
示例:
type Person struct {
/*
定义person结构体,存放person数据
*/
name string
sex string
age int
phone string
}
注:结构体当中要注意成员命名方式,
成员命名的首字母如果是大写,则表示该成员是公有的,其他包也可以访问;
成员命名的首字母如果是小写,则表示该成员是私有的,仅当前包可以访问;
结构体的数值传递属于值传递,eg:将结构体p1赋值给结构体p2;但可通过指针将结构体之间的传递变为引用类型,比如用new初始化结构体,得到的是一个结构体指针。
初始化:
func main() {
//结构体初始化
//法一:
var p1 Person
p1.age = 11
p1.name = "eden"
p1.phone = "110"
p1.sex = "man"
fmt.Println(p1)
//法二:
p2 := Person{
name: "jin",
sex: "man",
age: 111,
phone: "120",
}
fmt.Println(p2)
//法三:
/*
new
注:new返回的是指针,指向新分配的类型T的零值。可创建任意类型的指针
new创建的并不是一个nil指针,new创建指针之后会将其初始化为相应
类型的零值
*/
p3 := new(Person)
p3.sex = "woman"
p3.phone = "114"
p3.name = "marry"
p3.age = 18
fmt.Println(*p3)
p4 := p3
fmt.Println("p4:", p4)
p4.age = 20
fmt.Println(*p3, *p4)
}
/*result
{eden man 11 110}
{jin man 111 120}
{marry woman 18 114}
p4: &{marry woman 18 114}
{marry woman 20 114} {marry woman 20 114}
*/
结构体嵌套:
/*
结构体嵌套
Student Addresss
*/
type Address struct {
country string
city string
}
type Student struct {
name string
address Address
}
p5 := new(Student)
p5.name = "Tom"
p5.address = Address{
country: "China",
city: "Wuhan",
}
fmt.Println(*p5)
fmt.Println(p5.address.city)
p6 := Student{
name: "Jam",
address: Address{
city: "wuhan",
country: "China",
},
}
fmt.Println(p6)
p6.address.city = "beijing"
fmt.Println(*p5)
fmt.Println(p6)
/*result
{Tom {China Wuhan}}
Wuhan
{Jam {China wuhan}}
{Tom {China Wuhan}}
{Jam {China beijing}}
*/