zoukankan      html  css  js  c++  java
  • 【Go Time】Go语言 指针详解

    什么是指针

    请关注原作者公众号:Go编程时光

    当我们定义一个变量 name

    var name string = "Go指针"
    

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

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

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

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

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

    • 普通变量:存数据值本身
    • 指针变量:存值的内存地址

    指针的创建

    指针创建有三种方法

    第一种方法

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

    // 定义普通变量
    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)
    

    指针的创建

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

    package main
    
    import "fmt"
    
    func main() {
        astr := "hello"
        aint := 1
        abool := false
        arune := 'a'
        afloat := 1.2
        
        fmt.Printf("asgr 指针类型是:%T
    ", &astr)
        fmt.Printf("aint 指针类型是:%T
    ", &aint)
        fmt.Printf("abool 指针类型是:%T
    ", &abool)
        fmt.Printf("arune 指针类型是:%T
    ", &arune)
        fmt.Printf("afloat 指针类型是:%T
    ", &afloat)
    }
    

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

    astr 指针类型是:*string
    aint 指针类型是:*int
    abool 指针类型是:*bool
    arune 指针类型是:*int32
    afloat 指针类型是:*float
    

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

    func mytest(ptr *int) {
        fmt.Println(*ptr)
    }
    

    指针的零值

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

    func main() {
        a := 25
        var b *int // 声明一个指针
        
        if b == nil {
            fmt.Println(b) // <nil>
            b = &a // 初始化:将a的内存地址给b
            fmt.Println(b) // 0xc0000100a0
        }
    }
    

    指针与切片

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

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

    1. 将这个数组的切片作为参数传给函数
    2. 将患者数组的指针作为参数传给函数

    尽管二者都可以实现我们的目的,但是按照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,909,1}
        modify(&a)
        fmt.Println(a)
    }
    
  • 相关阅读:
    [转]给嵌入式系统工程师的十个建议
    About Career Links
    Oh My, JAVA?!
    All Maling-Lists
    ALSA Links
    [Music Links]
    [Android-Building]/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../liblzo2.so when searching for -llzo2
    Debugging for Unfortunately, the process android.process.media has stopped
    [Quote] How To Change, Customize & Create Android Boot Animation [Guide]
    Share folders on your local Windows PC to remote Linux PC
  • 原文地址:https://www.cnblogs.com/mengyilingjian/p/13712508.html
Copyright © 2011-2022 走看看