指针

指针:

  区别于 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\n", a, &a) // a:10 ptr:0xc00001a078
    fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
    fmt.Println(&b)                    // 0xc00000e018
}

  

 

 

指针取值:

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

func main() {
    //指针取值
    a := 10
    b := &a         // 取变量a的地址,将指针保存到b中
    fmt.Printf("type of b:%T\n", b)     // type of b:*int
    c := *b         // 指针取值(根据指针去内存取值)
    fmt.Printf("type of c:%T\n", c)     // type of c:int
    fmt.Printf("value of c:%v\n", 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 \n",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 \n",a)       // *int
    fmt.Printf("%T \n",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用于类型的内存分配,并且内存对应的值为类型的默认零值,返回的是 指向类型的指针。

 

posted on 2021-04-21 14:23  二十四岁半  阅读(59)  评论(0编辑  收藏  举报

导航