• go 指针


    go 指针

    指针是一种存储变量内存地址(Memory Address)的变量。在学习指针之前,建议先记住下面3句话。

    1. 类型前放 * 表示指针类型,这个类型的指针,指向这个类型的指针
    2. 在变量前加 & 取地址符号,表示取该变量的地址
    3. 在(指针)变量前加 * 表示反解,把地址解析成具体的值

    定义指针

    指针变量的类型为 *T,该指针指向一个 T 类型的变量。

    func main() {
    	var a int = 10 // 定义一个int类型的变量
    	var p *int // 定义一个整数类型的指针
    	p = &a //把a的地址给p
    	fmt.Println("a的地址为:",p)  // a的地址为: 0xc00000a098
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    指针的零值与解引用

    指针是引用类型,在go中,所有引用类型的零值都为 nil

    指针的解引用可以获取指针所指向的变量的值。将 a 解引用的语法是 *a

    func main() {
    	var a int = 10 // 定义一个int类型的变量
    	var p *int     // 定义一个整数类型的指针
    	if p == nil {
    		fmt.Println("指针的零值为nil")  // 指针的零值为nil
    	}
    	p = &a                      //把a的地址给p
    	fmt.Println("p的解引用值为:", *p) // p的解引用值为: 10
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    指针也是一个变量,因此也存在对应的内存地址,所以就会存在 指针的指针

    func main() {
    	var a int = 10 // 定义一个int类型的变量
    	var p *int     // 定义一个整数类型的指针
    	var m **int
    	p = &a                      //把a的地址给p
    	m = &p                      //把p的地址给m
    	fmt.Println("p的解引用值为:", *p)  // p的解引用值为: 10
    	fmt.Println("m的解引用值为:", *m)  // m的解引用值为: 0xc0000aa058  -> p的值
    	fmt.Println("a的值为:", **m)      // a的值为: 10
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    并且能够一直嵌套下去,也能够反解出值

    函数传递指针参数

    可以向函数传递指针类型参数,并且可以通过指针修改值,影响外部变量的值

    func main() {
       a := 10
       p := &a
       test(p)
       fmt.Println(a)  // 99
    }
    
    func test(p *int) {
       fmt.Println(p)  // 0xc00000a098
       fmt.Println(*p)  // 10
        *p = 99   // 修改值,不是改p,改p指向的值也就是a的值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    需要注意的是,不要向函数传递数组的指针,而应该使用切片,使用切片的好处是,如果数组长度变了,函数不需要重写,而如果使用数组的指针,则需要重写函数。

    func main() {
    	var a = [3]int{7,8,9}
    	var p *[3]int = &a
    	test2(p)
    	test3(a[:])
    }
    
    func test3(a []int)  {
    	fmt.Println(a)  // [7 8 9]
    }
    
    func test2(a *[3]int)  {
    	fmt.Println(*a)  // [7 8 9]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如果数组长度变成4,代码如下

    func main() {
    	var a = [4]int{7,8,9}
    	var p *[4]int = &a
    	test2(p)
    	test3(a[:])
    }
    func test3(a []int)  {   // 去切片不需要修改
    	fmt.Println(a)
    }
    
    func test2(a *[4]int)  {  // 函数必须修改,才能使用
    	fmt.Println(*a)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    如果是数组的指针,不需要解引用,直接使用即可,按索引取值即可

    func main() {
    	var a = [4]int{7,8,9}
    	test2(p)
    }
    
    func test2(a *[4]int)  {
    	fmt.Println(a[0])  // 7
    	fmt.Println(a[1])  // 8
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    指针数组与数组指针

    指针数组指数组里面放了一堆指针,数组指针指指向数组的指针

    func main() {
    	var a = [4]int{7,8,9}
        // 数组指针
        p := &a
    }
    
    // 指针数组
    func test4(p *[4]int)  {
        fmt.Println((*p)[1])  // 先对a解引用--->数组--->再取值-->8
        // (*p)[0]=10     先解引用,再修改   两种写法都可以
        p[0]=10  // 把数组第0个位置的值改成了 10
        fmt.Println(*p)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    YOLOv5、YOLOv8改进:C3STR(Swin Transformer)
    DevExpress 22.1.3 源代码版本-2022
    Kafka消息队列
    爬虫(14) - Scrapy-Redis分布式爬虫(1) | 详解
    【安卓应用渗透】第一篇:安卓逆向回顾和梳理-2211
    2024湖南师范大学计算机考研分析
    便于计算机处理的补数详解
    杏仁粉比大多数其他面粉都更好,你不会还不知道吧
    阿里云服务器如何关闭防火墙?阿里云安全组怎么设置端口?
    差点被这波Handler 面试连环炮带走~
  • 原文地址:https://blog.csdn.net/qq_55752792/article/details/125605791