zoukankan      html  css  js  c++  java
  • go 指针类型

    变量和内存地址

    每个变量都有内存地址,可以说通过变量来操作对应大小的内存

    var a int32
    a = 100
    fmt.Printf(“%d
    ”, a)
    fmt.Printf(“%p
    ”, &a)

    通过&符号可以获取变量的地址

    普通变量存储的是对应类型的值,这些类型就叫值类型

    var b int32
    b = 156
    fmt.Printf(“%d
    ”, b)
    fmt.Printf(“%p
    ”, &b)

    指针类型的变量存储的是一个地址,所以有叫指针类型或引用类型

    var b int32
    b = 156
    var a *int32
    a = &b

     指针类型定义,var 变量名 *类型

    package main
    import ( 
        "fmt"
    )
    func main() { 
        b := 255
        var a *int = &b
        fmt.Printf("Type of a is %T
    ", a)
        fmt.Println("address of b is", a)
    }

    指针类型变量的默认值为nil,也就是空地址

    package main
    import ( 
     "fmt"
    )
    func main() { 
        a := 25
        var b *int
        if b == nil {
            fmt.Println("b is", b)
            b = &a
            fmt.Println("b after initialization is", b)
        }
    }    

    如果操作指针变量指向的地址里面的值呢?

     通过* 符号可以获取指针变量指向的变量

    package main 
    import ( 
     "fmt"
    )
    func main() { 
      b := 255
      a := &b
      fmt.Println("address of b is", a)
      fmt.Println("value of b is",*a)
    }

     通过指针修改变量的值

    package main
    import ( 
     "fmt"
    )
    func main() { 
       b := 255
       a := &b
       fmt.Println("address of b is", a)
       fmt.Println("value of b is",*a)
       *a++
       fmt.Println("new value of b is", b)
    }

    举例

    package main
    
    import "fmt"
    
    // 定义指针
    func test1() {
        var a int = 100
        var b *int
        fmt.Printf("a 的值为: %v  a的内存地址是:%p  a的类型是%t
    ", a, &a, a)
        fmt.Printf("b 的值为: %v  b的内存地址是:%p  b的类型是%t
    ", b, &b, b)
    
        b = &a
        fmt.Printf("b 的值为: %v  b的内存地址是:%p  b的类型是%t
    ", b, &b, b)
    }
    
    /*
    a 的值为: 100  a的内存地址是:%!p(int=100)  a的类型是%!t(int=100)
    b 的值为: <nil>  b的内存地址是:0x0  b的类型是%!t(*int=<nil>)
    b 的值为: 0xc0000100a8  b的内存地址是:0xc0000100a8  b的类型是%!t(*int=0xc0000100a8)
    */
    
    //控指针
    func test2() {
        var a int = 100
        var b *int
        fmt.Printf("b 的值为: %v  b的内存地址是:%p  b的类型是%t
    ", b, &b, b)
        if b == nil {
            fmt.Println("b是一个空指针")
            b = &a
        }
        fmt.Printf("b 的值为: %v  b的内存地址是:%p  b的类型是%t
    ", b, &b, b)
    }
    
    /*
    b 的值为: <nil>  b的内存地址是:0xc000080018  b的类型是%!t(*int=<nil>)
    b是一个空指针
    b 的值为: 0xc000058080  b的内存地址是:0xc000080018  b的类型是%!t(*int=0xc000058080)
    */
    
    // 获取指针对应地址的值
    func test3() {
        var a int = 100
        var b *int
        b = &a
        fmt.Printf("b 的值为: %v  b的内存地址是:%p  b的类型是%t
    ", b, &b, b)
        fmt.Printf("b 中存储的内存地址对应的值为%v
    ", *b)
    
    }
    
    /*
    b 的值为: 0xc0000100a8  b的内存地址是:0xc000006028  b的类型是%!t(*int=0xc0000100a8)
    b 中存储的内存地址对应的值为100
    */
    
    // 改变指针存储地址对应的值
    func test4() {
        var a int = 100
        var b *int
        b = &a
        fmt.Printf("b 中存储的内存地址对应的值为%v
    ", *b)
        fmt.Printf("a的值为%v
    ", a)
        *b = 500
        fmt.Printf("b 中存储的内存地址对应的值为%v
    ", *b)
        fmt.Printf("a的值为%v
    ", a)
    
    }
    
    /*
    b 中存储的内存地址对应的值为100
    a的值为100
    b 中存储的内存地址对应的值为500
    a的值为500
    */
    
    func main() {
        // test1()
        // test2()
        test3()
        // test4()
    }

    指针变量传参

    package main
    import ( 
     "fmt"
    )
    func change(val *int) { 
      *val = 55
    }
    func main() { a :
    = 58 fmt.Println("value of a before function call is",a) b := &a change(b) fmt.Println("value of a after function call is", a) }
    package main
    import ( 
     "fmt"
    )
    func modify(arr *[3]int) { 
      (*arr)[0] = 90
    }
    func main() { 
      a := [3]int{89, 90, 91}
      modify(&a)
      fmt.Println(a)
    }

    切片传参  切片是应用类型

    package main
    import ( 
     "fmt"
    )
    func modify(sls []int) { 
      sls[0] = 90
    }
    func main() { 
      a := [3]int{89, 90, 91}
      modify(a[:])
      fmt.Println(a)
    }
    package main
    
    import "fmt"
    
    func test1() {
        var a int = 100
        var b *int
        b = &a
        fmt.Printf("a 的值为: %v  a的内存地址是:%p  a的类型是%t
    ", a, a, a)
        fmt.Printf("b 中存储的内存地址对应的值为%v
    ", *b)
        fmt.Printf("b 的值为: %v  b的内存地址是:%p  b的类型是%t
    ", b, b, b)
    
        a = 200
        fmt.Printf("a 的值为: %v  a的内存地址是:%p  a的类型是%t
    ", a, a, a)
        fmt.Printf("b 中存储的内存地址对应的值为%v
    ", *b)
        fmt.Printf("b 的值为: %v  b的内存地址是:%p  b的类型是%t
    ", b, b, b)
    
    }
    
    /*
    a 的值为: 100  a的内存地址是:%!p(int=100)  a的类型是%!t(int=100)
    b 中存储的内存地址对应的值为100
    b 的值为: 0xc000058080  b的内存地址是:0xc000058080  b的类型是%!t(*int=0xc000058080)
    a 的值为: 200  a的内存地址是:%!p(int=200)  a的类型是%!t(int=200)
    b 中存储的内存地址对应的值为200
    b 的值为: 0xc000058080  b的内存地址是:0xc000058080  b的类型是%!t(*int=0xc000058080)
    */
    
    func test2(a *int) {
        *a = 200
    }
    
    func test3(a *[3]int) {
        (*a)[0] = 1000
    }
    
    func test4(a []int){
        a[0] = 123
    
    }
    
    func modifytest() {
        // var a int = 2
        // test2(&a)
        // fmt.Printf("修改后a的值为 %d", a) //修改后a的值为 200
    
        // a := [3]int{1, 2, 3}
        // test3(&a)
        // fmt.Printf("修改后a的值为 %v", a) // 修改后a的值为 [1000 2 3]
    
    
        a:= [5]int{1,5,6,4,5}
        test4(a[:])
        fmt.Printf("修改后a的值为 %v", a) // 修改后a的值为 [123 5 6 4 5]
    }
    
    func main() {
        // test1()
    
        modifytest()
    }

    make 和 new

    make用来分配引用类型的内存,比如 map、slice以及channel

    new用来分配除引用类型的所有其他类型的内存,比如 int、数组等

    package main
    
    import "fmt"
    
    func testNew() {
        var a *int = new(int)
        *a = 100
        fmt.Printf("a=%v, a的内存地址%p, *a= v%  *a的内存地址%p
    ", a, a, *a, &(*a))
    
        var b *[]int = new([]int)
        *b = make([]int, 5, 10)
        (*b)[0] = 10
        fmt.Printf("b=%v, b的内存地址%p, *b= v%  *b的内存地址%p
    ", b, b, *b, &(*b))
    }
    
    func main() {
        testNew()
    }

    值拷贝和引用拷贝

    值拷贝

    package main
    import ( 
      "fmt"
    )
    func main() { 
      var a int = 100
      b := a
    }

     

    引用拷贝

    package main
    import ( 
      "fmt"
    )
    func main() { 
      var a int = 100
      var b *int = &a
      var c *int = b
      *c = 200
    }

    package main
    
    import "fmt"
    
    // 值拷贝
    func test1() {
        var a int = 100
        b := a
        fmt.Printf("a= %d, a的内存地址为%p
    ", a, &a)
        fmt.Printf("b= %d, b的内存地址为%p
    ", b, &b)
    
    }
    
    /*
    a= 100, a的内存地址为0xc000058080
    b= 100, b的内存地址为0xc000058088
    */
    
    // 引用拷贝
    func test2() {
        var a int = 10
        var b *int
        b = &a
        fmt.Printf("a= %d, a的内存地址为%p
    ", a, &a)
        fmt.Printf("b= %v, b的内存地址为%p *b=%d
    ", b, &b, *b)
    
        *b = 100
        fmt.Printf("a= %d, a的内存地址为%p
    ", a, &a)
        fmt.Printf("b= %v, b的内存地址为%p *b=%d
    ", b, &b, *b)
    }
    
    /*
    a= 10, a的内存地址为0xc000058080
    b= 0xc000058080, b的内存地址为0xc000080018 *b=10
    a= 100, a的内存地址为0xc000058080
    b= 0xc000058080, b的内存地址为0xc000080018 *b=100
    */
    
    func test3() {
        var a [3]int = [3]int{1, 2, 3}
        var b *[3]int
    
        b = &a
    
        fmt.Printf("a= %d, a的内存地址为%p
    ", a, &a)
        fmt.Printf("b= %v, b的内存地址为%p *b=%d
    ", b, &b, *b)
    
        (*b)[1] = 100
        fmt.Printf("a= %d, a的内存地址为%p
    ", a, &a)
        fmt.Printf("b= %v, b的内存地址为%p *b=%d
    ", b, &b, *b)
        
        
    }
    /*
    a= [1 2 3], a的内存地址为0xc0000560c0
    b= &[1 2 3], b的内存地址为0xc000080018 *b=[1 2 3]
    a= [1 100 3], a的内存地址为0xc0000560c0
    b= &[1 100 3], b的内存地址为0xc000080018 *b=[1 100 3]
    */
    
    
    func main() {
        // test1()
        // test2()
        test3()
    }

    练习 交换两个变量的值

    package main
    
    import "fmt"
    
    func swap1(a int, b int) {
        fmt.Printf("swap  交换前 a= %d b=%d
    ", a, b)
        a, b = b, a
        fmt.Printf("swap  交换后 a= %d b=%d
    ", a, b)
    }
    
    func swap2(a *int, b *int) {
        fmt.Printf("swap  交换前 a= %d b=%d
    ", *a, *b)
        *a, *b = *b, *a
        fmt.Printf("swap  交换后 a= %d b=%d
    ", *a, *b)
    }
    
    func main() {
        var a int = 10
        var b int = 20
        // fmt.Printf("main  交换前 a= %d b=%d
    ", a, b)
        // swap1(a, b)
        // fmt.Printf("main  交换后 a= %d b=%d
    ", a, b)
    
        /*
            main  交换前 a= 10 b=20
            swap  交换前 a= 10 b=20
            swap  交换后 a= 20 b=10
            main  交换后 a= 10 b=20
        */
    
        var c *int
        var d *int
    
        c = &a
        d = &b
        
        fmt.Printf("main  交换前 a= %d b=%d
    ", a, b)
        swap2(c, d)
        fmt.Printf("main  交换后 a= %d b=%d
    ", a, b)
    
        /*
        main  交换前 a= 10 b=20
        swap  交换前 a= 10 b=20
        swap  交换后 a= 20 b=10
        main  交换后 a= 20 b=10
        */
    }
  • 相关阅读:
    【SQL跟踪工具】SQL Profiler 跟踪器
    使用Fiddler调试手机端页面请求/抓包
    SQL 常用判断语句
    VS中常用快捷键
    博客园博客自动生成目录/目录索引
    BZOJ 1135 P3488 LYZ-Ice Skates 线段树+Hall
    BZOJ 4823 老C的方块
    POJ
    BZOJ 1299 [LLH邀请赛]巧克力棒
    BZOJ 2437 [Noi2011]兔兔与蛋蛋
  • 原文地址:https://www.cnblogs.com/ctztake/p/10328194.html
Copyright © 2011-2022 走看看