zoukankan      html  css  js  c++  java
  • 指针

    指针:

      区别于 C/C++ 中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。

      Go中指针的3个概念:指针地址,指针类型,指针取值。

    Go语言中的指针:

      Go语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量。传递数据使用指针,而不需要拷贝数据。类型指针不能进行偏移和运算。

      Go中指针只有两个操作,& 取地址,* 根据地址取值

    指针地址与指针类型:

      每个变量在运行时都有一个内存地址。Go中使用 &变量 进行取地址操作。Go中的值类型都有对应的指针类型,比如:*int,*string 等。

           ptr := &v     
           v:  代表被取地址的变量,变量的类型为T
           ptr:接收地址的变量,ptr的类型为 *T,称作T的指针变量。*代表指针
    func main() {
        a := 10
        b := &a
        fmt.Printf("a:%d ptr:%p
    ", a, &a) // a:10 ptr:0xc00001a078
        fmt.Printf("b:%p type:%T
    ", b, b) // b:0xc00001a078 type:*int
        fmt.Println(&b)                    // 0xc00000e018
    }
    

      

    指针取值:

       对变量使用&操作获取地址后,会获得这个变量的指针,可以对指针使用*操作,对指针进行取值。

    func main() {
        //指针取值
        a := 10
        b := &a         // 取变量a的地址,将指针保存到b中
        fmt.Printf("type of b:%T
    ", b)     // type of b:*int
        c := *b         // 指针取值(根据指针去内存取值)
        fmt.Printf("type of c:%T
    ", c)     // type of c:int
        fmt.Printf("value of c:%v
    ", c)    // value of c:10
    }

      取地址操作符& 和 取值操作符* 是一对互补操作符,&取出地址,*根据地址取出 地址指向的值

      变量,指针地址,指针变量,取地址,取值 的相互关系和特性如下:

    1.   对变量进行取地址操作&,可以获得这个变量的 指针变量
    2.   指针变量的值,就是 指针地址
    3.   对 指针变量进行取值操作*,可以获得指针变量指向的原变量的值,
      
    package main
    
    import "fmt"
    
    func modify1(x int) {
        x = 100
    }
    
    func modify2(x *int) {
        *x = 200
    }
    
    func main() {
    
        x := 10
        modify1(x)
        fmt.Println(x)      // 10
        modify2(&x)
        fmt.Println(x)      // 200
    
    }
    指针传值,示例

    空指针:

      当一个指针被定义后没有分配到任何变量时,它的值为 nil,即 空指针

      
    package main
    
    import "fmt"
    
    func main() {
    
        var p *string
    
        fmt.Println(p)
        fmt.Printf("p的值是 %v 
    ",p)
    
        if p != nil {
            fmt.Println("p不是空值")
        } else {
            fmt.Println("p是空值")
        }
        
    }
    代码示例

    new 和 make:

    package main
    
    import "fmt"
    
    func main() {
    
        var a *int
        *a = 100
        fmt.Println(*a)
    
        var b map[string]int
        b["测试"] = 100
        fmt.Println(b)
    
    }
    

      执行上面的代码会引发panic

      在Go中,对于引用类型的变量,我们在使用的时候,不仅要声明它,还要为它分配内存空间,否则就没有办法存储值。

      对于值类型的声明不需要分配内存空间,因为在声明的时候,就已经默认分配好了内存空间。

      要分配内存,需要使用make和new,他们是两个内建的函数,主要用来分配内存。

    new:

        func new(Type) *Type
        Type表示类型,new函数只接收一个参数,这个参数是一个类型
        *Type表示类型指针,new函数返回一个指向该类型内存地址的指针
      new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。
    package main
    
    import "fmt"
    
    func main() {
    
        a := new(int)
        b := new(bool)
    
        fmt.Printf("%T 
    ",a)       // *int
        fmt.Printf("%T 
    ",b)       // *bool
    
        fmt.Println(*a)             // 0
        fmt.Println(*b)             // false
    
    }
    package main
    
    import "fmt"
    
    func main() {
    
        var a *int
        a = new(int)
        *a = 10
        fmt.Println(*a)
    
    }
    

      var a *int,只是声明了一个指针变量a,但是没有初始化,指针作为引用类型需要初始化后才能拥有内存空间,才可以赋值。

    make

      make也是用于内存分配的,区别于new,它只用于slice,chan以及map的内存创建,而且它返回的类型就是三个类型的本身,而不是他们的指针类型,因为这三种类型就是引用类型,没必要返回他们的指针。

       func make(t Type, size ...IntegerType) Type

      make函数是无可替代的,我们在使用slice,map以及channel的时候,都需要使用make进行初始化,然后才可以对它们进行操作。

    package main
    
    import "fmt"
    
    func main() {
    
        var b map[string]int
        b = make(map[string]int,10)
        b["测试"] = 100
        fmt.Println(b)          // map[测试:100]
    
    }
    

      

    new 与 make 的区别:

      都是用来做内存分配的

      make只用于 slice,map,channel的初始化,返回的是 这三个引用类型的本身

      new用于类型的内存分配,并且内存对应的值为类型的默认零值,返回的是 指向类型的指针。

  • 相关阅读:
    430flash的操作
    430单片机之定时器A功能的大致介绍
    MSP430看门狗
    430之通用异步串口通信模块
    430的启动,I/O中断
    Msp430概述
    烦躁
    12864密码锁
    单片机的动手实践篇--51单片机玩转12864
    【CSS】font样式简写(转)- 不是很建议简写
  • 原文地址:https://www.cnblogs.com/yizhixiaowenzi/p/14685069.html
Copyright © 2011-2022 走看看