美文网首页Go语言实践
第四章:Go语言指针

第四章:Go语言指针

作者: 楚江云 | 来源:发表于2019-11-02 17:44 被阅读0次
    golang-gopher.png

    1. 指针类型

    指针就是存储变量内存地址的变量,指针也是一种变量,我们称之为指针变量

    声明一个 T 类型的指针,指针声明之后默认值都是nil

    package main
    
    import "fmt"
    
    func main() {
        // 声明一个int类型指针
        var p *int
        // 声明一个string类型指针
        var s *string
        // 声明一个bool类型指针
        var b *bool
        // 声明一个interface类型指针
        var i *interface{}
        fmt.Printf("p default value = %v  p type = %T\n",p,p)
        fmt.Printf("s default value = %v  p type = %T\n",s,s)
        fmt.Printf("b default value = %v  p type = %T\n",b,b)
        fmt.Printf("i default value = %v  p type = %T\n",i,i)
    }
    
    
    p default value = <nil>  p type = *int
    s default value = <nil>  p type = *string
    b default value = <nil>  p type = *bool
    i default value = <nil>  p type = *interface {}
    

    指针的初始化和基本使用

    package main
    
    import "fmt"
    
    func main() {
        // 声明一个整型变量 n 并且初始化赋值为99
        var n int = 99
        // 获取n在内存中的地址,使用 & 符号取一个变量的地址
        fmt.Println("整型变量n的地址是 :", &n)
        // 声明一个指针变量p 类型是int指针类型
        var p *int
        // 整数指针变量p初始化赋值,将整数变量n的地址赋给指针变量p
        p = &n
        // 打印p的值(保存的是n的内存地址)
        fmt.Println("指针变量p的值是   :", p)
        // 指针变量p本身也有一个内存地址
        fmt.Println("指针变量P本身的内存地址是", &p)
        // 通过 * 访问指向变量的值
        fmt.Println("指针变量p指向变量的值是 :", *p)
        // 修改指针变量p指向变量n的值
        fmt.Println("整型变量n的值是", n)
        *p = 100
        // 查看n的值被改变了
        fmt.Println("修改后整型变量n的值是", n)
    
    }
    
    
    整型变量n的地址是 : 0xc000054080
    指针变量p的值是   : 0xc000054080
    指针变量P本身的内存地址是 0xc000080020
    指针变量p指向变量的值是 : 99
    整型变量n的值是 99
    修改后整型变量n的值是 100
    

    当指针变量没有指向的时候不能进行 (*p)的操作

    package main
    
    import "fmt"
    
    func main() {
        var p *int
        // panic: runtime error: invalid memory address or nil pointer dereference
        fmt.Println(*p)
    }
    
    

    也就是说指针变量要使用应该给它初始化一个内存

    内置new()函数也可创建指针,new() 是一个内存分配函数,传入的参数是一个类型,且返回指向的指针

    // The new built-in function allocates memory. The first argument is a type,
    // not a value, and the value returned is a pointer to a newly
    // allocated zero value of that type.
    func new(Type) *Type
    
    package main
    
    import (
        "fmt"
    )
    
    func main() {
        // 指针变量初始化方法1
        fmt.Println("指针变量初始化方法1")
        var p *int
        var i int
        fmt.Println(&i)
        p = &i
        fmt.Println(p)
        fmt.Println(*p)
        fmt.Println("指针变量初始化方法2")
        var p2 *int
        // 使用new()函数初始化
        p2 = new(int)
        fmt.Println(p2)
        fmt.Println(*p2)
        // 和上面类似就是写法不同
        fmt.Println("指针变量初始化方法3")
        p3 := new(int)
        fmt.Println(p3)
        fmt.Println(*p3)
        // 类型推导
        var p4 = &i
        fmt.Printf("p4 value = %v ,type = %T \n",p4,p4)
    }
    
    指针变量初始化方法1
    0xc000054090
    0xc000054090
    0
    指针变量初始化方法2
    0xc000054098
    0
    指针变量初始化方法3
    0xc0000540a0
    0
    p4 value = 0xc000054090 ,type = *int 
    

    指针可以指向任何类型变量,也包括指向另一个指针

    package main
    
    import "fmt"
    
    func main(){
        var i int = 100
        var p1 = &i
        fmt.Printf("i type is %T, value = %v, memory address = %v\n",i,i,&i)
        fmt.Printf("p type is %T, value = %v, memory address = %v\n",p1,p1,&p1)
        // 创建一个指向指针的指针变量
        var p2 = &p1
        fmt.Printf("p2 type is %T, value = %v\n",p2,p2)
        // 访问的是p1变量的值,而p1也是指针变量,它的值就是一个内存地址
        fmt.Println(*p2)
        // 等价于 *p1 最终访问的是整型变量i的值
        fmt.Println(**p2)
        fmt.Println(*(*p2))
    }
    
    
    i type is int, value = 100, memory address = 0xc000054080
    p type is *int, value = 0xc000054080, memory address = 0xc000080018
    p2 type is **int, value = 0xc000080018
    0xc000054080
    100
    100
    

    Go语言中类型指针不能进行偏移和运算

    因为这样的语言特点,带来的优势是指针变量高效的访问, 但又不会发生指针偏移,同时垃圾回收也比较容易

    package main
    
    import "fmt"
    
    func main() {
        var i int = 98
        var p *int = &i
        var p1 = &i
        // invalid operation: p + p1 (operator + not defined on pointer)
        var p2 = p + p1
        //invalid operation: p1 + 2 (mismatched types *int and int)
        var p3 = p1 + 2
        fmt.Println(p1)
    }
    

    指针变量可以使用关系运算符 == 比较 ,但是不能进行 > 或者 < 比较

    package main
    
    import "fmt"
    
    func main() {
        var i1 int8 = 90
        var i2 int64 = 80
        var i3 int8 = 70
        var p1 *int8 = &i1
        var p2 *int64 = &i2
        var p3 = &i2
        var p4 = &i3
        fmt.Println(p1)
        fmt.Println(p2)
        fmt.Println(p3)
        // p2 == p3
        if p2 == p3 {
            fmt.Println("p2 == p3")
        }
        //invalid operation: p2 > p1 (mismatched types *int64 and *int8)
        if p2 > p1 {
            fmt.Println("")
        }
        // invalid operation: p1 < p4 (operator < not defined on pointer)
        if p1 < p4{
            fmt.Println("p1 < p4")
        }
    
    }
    

    指针可以作为参数传递

    package main
    
    import "fmt"
    
    // 函数的形参是一个整型指针类型
    func modifyVar(p *int) {
        *p += 100
    }
    func exchangevar(i, j *int) {
        *i, *j = *j, *i
    }
    func main() {
        var i int = 1
        fmt.Println(i)
        modifyVar(&i)
        fmt.Println(i)
        var x, y int = 66, 99
        // 交换前的值
        fmt.Println("x = ", x)
        fmt.Println("y = ", y)
        // 交换后的值
        exchangevar(&x, &y)
        fmt.Println("x = ", x)
        fmt.Println("y = ", y)
    }
    
    
    1
    101
    x =  66
    y =  99
    x =  99
    y =  66
    

    案例: 使用指针变量获取命令行输入信息

    package main
    
    import (
        "flag"
        "fmt"
    )
    //定义一个叫做mode的指令变量 *string类型
    var mode = flag.String("mode","","process mode")
    func main() {
        // 解析命令行参数,将结果写入创建的指令变量中
        flag.Parse()
        if *mode == "fast"{
            fmt.Println("fast mode execute")
        }else if *mode == "slow" {
            fmt.Println("slow mode execute")
        }else {
            fmt.Println("default mode execute")
        }
    }
    
    $ go run main.go --mode=fast
    fast mode execute
    

    相关文章

      网友评论

        本文标题:第四章:Go语言指针

        本文链接:https://www.haomeiwen.com/subject/omlhbctx.html