07. 详解数据类型:指针(07.0是多大鞋码)

网友投稿 244 2022-08-17

07. 详解数据类型:指针(07.0是多大鞋码)

0. 什么是指针

当我们定义一个变量 name

var name string = "Go编程时光"

此时,name 是变量名,它只是编程语言中方便程序员编写和理解代码的一个标签。

当我们访问这个标签时,机算机会返回给我们它指向的内存地址里存储的值:Go编程时光。

出于某些需要,我们会将这个内存地址赋值给另一个变量名,通常叫做 ptr(pointer的简写),而这个变量,我们称之为指针变量。

换句话说,指针变量(一个标签)的值是指针,也就是内存地址。

根据变量指向的值,是否是内存地址,我把变量分为两种:

普通变量:存数据值本身

指针变量:存值的内存地址

1. 指针的创建

指针创建有三种方法

第一种方法

先定义对应的变量,再通过变量取得内存地址,创建指针

// 定义普通变量

aint := 1

// 定义指针变量

ptr := &aint     

第二种方法

先创建指针,分配好内存后,再给指针指向的内存地址写入对应的值。

// 创建指针

astr := new(string)

// 给指针赋值

*astr = "Go编程时光"

第三种方法

先声明一个指针变量,再从其他变量取得内存地址赋值给它

aint := 1

var bint *int  // 声明一个指针

bint = &aint   // 初始化

上面的三段代码中,指针的操作都离不开这两个符号:

& :从一个普通变量中取得内存地址

* :当 * 在赋值操作值的右边,是从一个指针变量中取得变量值,当*在赋值操作值的左边,是指该指针指向的变量

通过下面这段代码,你可以熟悉这两个符号的用法

package main

import "fmt"

func main() {

    aint := 1     // 定义普通变量

    ptr := &aint  // 定义指针变量

    fmt.Println("普通变量存储的是:", aint)

    fmt.Println("普通变量存储的是:", *ptr)

    fmt.Println("指针变量存储的是:", &aint)

    fmt.Println("指针变量存储的是:", ptr)

}

输出如下

普通变量存储的是:1

普通变量存储的是:1

指针变量存储的是: 0xc0000100a0

指针变量存储的是: 0xc0000100a0

要想打印指针指向的内存地址,方法有两种

// 第一种

fmt.Printf("%p", ptr)

// 第二种

fmt.Println(ptr)

2. 指针的类型

我们知道字符串的类型是 string,整型是int,那么指针如何表示呢?

写段代码试验一下就知道了

package main

import "fmt"

func main() {

    astr := "hello"

    aint := 1

    abool := false

    arune := 'a'

    afloat := 1.2

    fmt.Printf("astr 指针类型是:%T\n", &astr)

    fmt.Printf("aint 指针类型是:%T\n", &aint)

    fmt.Printf("abool 指针类型是:%T\n", &abool)

    fmt.Printf("arune 指针类型是:%T\n", &arune)

    fmt.Printf("afloat 指针类型是:%T\n", &afloat)

}

输出如下,可以发现用 *+所指向变量值的数据类型,就是对应的指针类型。

astr 指针类型是:*string

aint 指针类型是:*int

abool 指针类型是:*bool

arune 指针类型是:*int32

afloat 指针类型是:*float64

所以若我们定义一个只接收指针类型的参数的函数,可以这么写

func mytest(ptr *int)  {

    fmt.Println(*ptr)

}

3. 指针的零值

当指针声明后,没有进行初始化,其零值是 nil。

func main() {  

    a := 25

    var b *int  // 声明一个指针

    if b == nil {

        fmt.Println(b)

        b = &a  // 初始化:将a的内存地址给b

        fmt.Println(b)

    }

}

输出如下

0xc0000100a0

4. 指针与切片

切片与指针一样,都是引用类型。

如果我们想通过一个函数改变一个数组的值,有两种方法

将这个数组的切片做为参数传给函数

将这个数组的指针做为参数传给函数

尽管二者都可以实现我们的目的,但是按照 Go 语言的使用习惯,建议使用第一种方法,因为第一种方法,写出来的代码会更加简洁,易读。具体你可以参数下面两种方法的代码实现

使用切片

func modify(sls []int) {  

    sls[0] = 90

}

func main() {  

    a := [3]int{89, 90, 91}

    modify(a[:])

    fmt.Println(a)

}

使用指针

func modify(arr *[3]int) {  

    (*arr)[0] = 90

}

func main() {  

    a := [3]int{89, 90, 91}

    modify(&a)

    fmt.Println(a)

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:08. 面向对象编程:结构体与继承(08年出生的今年几岁)
下一篇:05. 详解数据类型:数组与切片(05,12,17,19,24,32,07)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~