您的位置:首页 > 编程语言 > Go语言

GoLang学习十三:指针

2020-07-24 21:01 281 查看

一、指针

1.1指针的概念

指针是存储另-个变量的内存地址的变量。

我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。

一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。

在上面的图中,变量b的值为156,存储在内存地址0x1040a124。
变量a持有b的地址,现在a被认为指向b。

1.2获取变量的地址

Go语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址。

a := 10
fmt.Println("a的数值:", a) // 10
fmt.Printf("a的类型:%T\n", a) // int
fmt.Printf("a的地址:%p\n", &a) // 0xc0000160b0
fmt.Println("a的地址:", &a) // 0xc0000160b0

1.3声明指针

声明指针,*T是指针变量的类型,它指向T类型的值的内存地址。
p1 = &a
*p1 = a

通过 p1 就能去操作 变量a ,因为p1和a的地址都是一样的

指针的指针
var p2 **int
p2 = &p1

*p2 == p1
**p2 == a

a := 10
fmt.Println("a的数值:", a) // 10
fmt.Printf("a的类型:%T\n", a) // int
fmt.Printf("a的地址:%p\n", &a) // 0xc0000a0068
fmt.Println("a的地址:", &a) // 0xc0000a0068

// 创建指针存储变量a的地址
var p1 *int
fmt.Println(p1) // <nil>
p1 = &a // p1指向a的内存地址
fmt.Println("a的地址",p1) // 0xc0000a0068
fmt.Println("p1的地址:", &p1) // 0xc0000ca020
fmt.Println("p1的数值是a的地址,该地址存储的数据(a的值):", *p1) // 10

fmt.Println(p1 == &a) // true
fmt.Println(*p1 == a) // true

*p1 = 200
fmt.Println(a) // 200

var p2 **int
fmt.Println(p2)
p2 = &p1
fmt.Printf("%T, %T, %T\n",a,p1,p2) // int, *int, **int
fmt.Println(p2 == &p1) // true
fmt.Println(*p2 == p1) // true
fmt.Println(**p2 == a) // true
**p2 = 300
fmt.Println(a) // 300

1.4 数组指针和指针数组

  • 数组指针:首先是一个指针,存放一个数组的地址
  • 指针数组:首先是一个数组,存储的数据类型是指针
*[5]float64,  指针,一个存储了5个浮点类型数据的数组的指针
*[3]string,   指针,数组的指针,存储了3个字符串
[3]*string,   数组,存储了5个浮点数据的地址的数组
[5]*float64,  数组,存储了5个浮点数据的地址的数组
*[5]*float64, 指针,存储了4个字符串数据的数组的指针的指针
*[3]*string,  指针,存储了3个字符串的指针地址的数组的指针
**[4]string,  指针,存储了4个字符串数据的数组的指针的指针
**[4]*string, 指针,存储了4个字符串的指针地址的数组,的指针的指针

数组指针

arr1 := [4]int{1, 2, 3, 4}

// 数组指针
p3 := &arr1
fmt.Printf("%T\n",p3) // *[4]int
fmt.Println(*p3) // [1 2 3 4]
fmt.Println(p3) // &[1 2 3 4]
fmt.Println(&arr1) // &[1 2 3 4]
fmt.Printf("%p\n",p3) // 0xc00009e1a0
fmt.Printf("%p\n",&p3) // 0xc0000ca028
(*p3)[0] = 100
fmt.Println(*p3) // [100 2 3 4]
fmt.Println(arr1) // [100 2 3 4]

p3[0] = 200 // 简化写法
fmt.Println(*p3) // [200 2 3 4]
fmt.Println(arr1) // [200 2 3 4]

指针数组

// 指针数组
b := 1
c := 2
d := 3
arr2 := [3]int{b, c, d}
arr3 := [3]*int{&b, &c, &d}
fmt.Printf("%p, %p, %p\n",&b,&c,&d) // 0xc0000161d8, 0xc0000161e0, 0xc0000161e8
// 数组是值传递
fmt.Printf("%p, %p, %p\n",&arr2[0],&arr2[1],&arr2[2])// 0xc00000c600, 0xc00000c608, 0xc00000c610
fmt.Println(arr2) // [1 2 3]
fmt.Println(arr3) // [0xc0000161d8 0xc0000161e0 0xc0000161e8]
fmt.Println(*arr3[0],*arr3[1],*arr3[2]) // 1 2 3

1.5 函数指针和指针函数

  • 函数指针:一个指针,指向了一个函数的指针。因为go语言中,function, 默认看作一个指针,没有*。slice , map, function
  • 指针函数:一个函数,该函数的返回值是一个指针。

指针函数

func main() {
p4 := fun1()
fmt.Println(p4) // &[1 2 3 4]
fmt.Println(*p4) // [1 2 3 4]
}
func fun1() *[4]int {
arr1 := [4]int{1,2,3,4}
return &arr1
}

1.6 指针作为参数

参数的传递:值传递、引用传递

func main() {
num := 10
fmt.Println("fun2()调用前,num的值",num) // 10
fun2(num)
fmt.Println("fun2()调用后,num的值",num) // 10

fmt.Println("fun3()调用前,num的值",num) // 10
fun3(&num)
fmt.Println("fun3()调用后,num的值",num) // 100
}
func fun2(num int) {
fmt.Println("fun2()函数中,num的值",num) // 10
num = 100
fmt.Println("fun2()函数中修改,num的值",num) // 100
}

func fun3(p *int) {
fmt.Println("fun2()函数中,num的值",*p) // 10
*p = 100
fmt.Println("fun2()函数中修改,num的值",*p) // 100
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: