zoukankan      html  css  js  c++  java
  • Go指针

    Go 语言指针

    Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。

    接下来让我们来一步步学习 Go 语言指针。

    我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。

    Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

    以下实例演示了变量在内存中地址:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main(){
     8     var name string
     9     name = "demon"
    10     fmt.Println("name变量的指针地址:",&name)
    11 }

    以上代码运行返回的结果:

    name变量的指针地址: 0xc420076050

    什么是指针

    一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。

    类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下:

    var var_name(变量名) *var_name_type(数据类型)

    var_name就是变量的名称,var_name_type是指针的数据类型,*用于指定变量是一个指针,例如以下的指针声明

    var name *string            //指向字符串类型的指针
    var age  *int                //指向整数型类型的指针

    如何使用指针

    指针使用流程:

    • 定义指针变量。
    • 为指针变量赋值。
    • 访问指针变量中指向地址的值。

    在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 
     8 func main(){
     9     //定义局部变量num1 num2
    10     var num1 int = 50
    11     var num2 *int
    12 
    13     //获取num1变量的内存地址并赋值给num2变量
    14     num2 = &num1
    15 
    16     fmt.Println("num1变量的内存地址为:", &num1)
    17     fmt.Println("num2变量指针的地址为:", num2)
    18 
    19     //获取变量num1的值
    20     fmt.Println("num1变量的值为:", num1)
    21     //获取变量num2的值
    22     fmt.Println("num2变量的值为:", *num2)
    23 
    24 }

    以上代码返回的运行结果:

    num1变量的内存地址为: 0xc42006e178
    num2变量指针的地址为: 0xc42006e178
    num1变量的值为: 50
    num2变量的值为: 50

    Go 空指针

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

    nil 指针也称为空指针。

    nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

    一个指针变量通常缩写为 ptr。

    查看以下实例:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main(){
     8     //初始化局部变量 ptr s 分别都是空指针
     9     var ptr  *int
    10     var s      *string
    11     //初始化局部变量num1 num2,因为num1赋值了并且num2的指针指向了num1
    12     var num1 float32 = 50.123
    13     var num2 *float32
    14     num2 = &num1
    15 
    16     //分别输出变量的值
    17     fmt.Printf("ptr的空指针的值为:%v
    ", ptr)
    18     fmt.Printf("s的空指针的值为:%v
    ", s)
    19     fmt.Printf("num2的值为%v
    ", *num2)
    20 
    21     //做判断,如果是空指针的话值就是nil
    22     if ptr == nil{
    23         fmt.Println("ptr是空指针哦~")
    24     }
    25 
    26     if s == nil{
    27         fmt.Println("s是空指针哦~")
    28     }
    29 
    30     if num2 == nil{
    31         fmt.Println("num2的是空指针哦~")
    32     }else {
    33         fmt.Println("num2的值为:", *num2)
    34     }
    35 
    36 }

    以上代码返回的运行结果:

    ptr的空指针的值为:<nil>
    s的空指针的值为:<nil>
    num2的值为50.123
    ptr是空指针哦~
    s是空指针哦~
    num2的值为: 50.123

    Go 语言指针数组

    number为整型指针数组。因此每个元素都指向了一个值。以下实例的三个整数将存储在指针数组中:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main(){
     8     //定义一个blance数组,并且拥有五个元素
     9     var blance = [5] int {1,2,3,4,5}
    10     //定义常量MAX为5
    11     const MAX int =  5
    12     //定义数组指针number
    13     var number [MAX] *int
    14 
    15     for i := 0; i< MAX; i++{
    16         //分别给number的数组中的每个索引赋值,值是引用blance数组中的每个元素的内存地址
    17         number[i] = &blance[i]
    18         fmt.Printf("blance[%d] = %d 
    ", i, blance[i])
    19     }
    20 
    21     fmt.Println("----------------------")
    22 
    23     for i := 0; i< MAX; i++{
    24         fmt.Printf("number[%d] = %d 
    ", i, *number[i])
    25     }
    26 
    27     fmt.Println("----------------------")
    28 
    29     for i := 0; i< MAX; i++{
    30         //如果blance数组与number数组一样,并且里面只的内存地址都一样,则打印两个数组元素的内存地址
    31         if blance[i] == *number[i] && &blance[i] == number[i]{
    32             fmt.Printf("blance[%d] %v   number[%d]  %v 
    ",i , &blance[i], i ,number[i])
    33 
    34         }
    35     }
    36 }

    以上代码返回的运行结果:

    blance[0] = 1 
    blance[1] = 2 
    blance[2] = 3 
    blance[3] = 4 
    blance[4] = 5 
    ----------------------
    number[0] = 1 
    number[1] = 2 
    number[2] = 3 
    number[3] = 4 
    number[4] = 5 
    ----------------------
    blance[0] 0xc4200141e0   number[0]  0xc4200141e0 
    blance[1] 0xc4200141e8   number[1]  0xc4200141e8 
    blance[2] 0xc4200141f0   number[2]  0xc4200141f0 
    blance[3] 0xc4200141f8   number[3]  0xc4200141f8 
    blance[4] 0xc420014200   number[4]  0xc420014200 

    来来来来,用Python来嘲讽一波golang的数组引用赋值~

     1 #!/usr/bin/env python3
     2 # _*_coding:utf-8_*_
     3 
     4 __author__ = 'demon'
     5 
     6 #声明列表l1
     7 l1 = ['demon','18','beijing',"python","golang","linux"]
     8 #浅拷贝列表l1中的每个元素
     9 l2 = l1[:]
    10 
    11 l1_len = len(l1)
    12 
    13 for i in range(l1_len):
    14     #判断列表中每个元素的内存地址是否一致
    15     if id(l1[i]) == id(l2[i]):
    16         #打印两个列表中给的每个元素及内存地址
    17         print("l1[{}]   {:10}   l2[{}]  {:10} at {memory}".format(i,l1[i],i,l2[i],memory=id(l1[i])))

    以上代码返回的运行结果:

    l1[0]   demon        l2[0]  demon      at 4302152624
    l1[1]   18           l2[1]  18         at 4330894536
    l1[2]   beijing      l2[2]  beijing    at 4330894200
    l1[3]   python       l2[3]  python     at 4329981408
    l1[4]   golang       l2[4]  golang     at 4330894984
    l1[5]   linux        l2[5]  linux      at 4329974728

    Go 语言指向指针的指针

    如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。

    当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:

    指向指针的指针变量声明格式如下:

    var ptr **int;

    以上指向指针的指针变量为整型。

    访问指向指针的指针变量值需要使用两个 * 号,如下所示:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func main() {
     8 
     9     var a int
    10     var ptr *int
    11     var pptr **int
    12 
    13     a = 3000
    14 
    15     //指针ptr地址
    16     ptr = &a
    17 
    18     //指向指针ptr地址
    19     pptr = &ptr
    20 
    21     //*获取pptr的值
    22     fmt.Printf("变量 a = %d
    ", a )
    23     fmt.Printf("指针变量 *ptr = %d
    ", *ptr )
    24     fmt.Printf("指向指针的指针变量 **pptr = %d
    ", **pptr)
    25 }

    以上代码返回的运行结果:

    变量 a = 3000
    指针变量 *ptr = 3000
    指向指针的指针变量 **pptr = 3000

    Go 语言指针作为函数参数

    Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。

    以下实例演示了如何向函数传递指针,并在函数调用后修改函数内的值:

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 //可以接收指针作为参数的自定义函数
     8 func person(name *string,age *int) string {
     9     //修改指针指向的name变量的值,影响了name的值
    10     *name = "大佬"
    11     fmt.Println("person函数内部的name的内存地址:", name)
    12     fmt.Printf("person函数内部的修改后name变量值:%s", *name)
    13     return  ""
    14 
    15 }
    16 
    17 func swap(x ,y int) string{
    18     //修改x,y的值,x,y作为局部变量传递进来,因为没有使用指针,所以不会影响函数外部的x,y变量值
    19     x, y = 50,100
    20     fmt.Println("swap函数内部的x变量值:", x)
    21     fmt.Println("swap函数内部的y变量值:", y)
    22     return ""
    23 }
    24 
    25 func main() {
    26     //初始化局部变量
    27     var name string = "demon"
    28     var    age     int = 18
    29     var x int = 10
    30     var y int = 20
    31 
    32     fmt.Println("person函数内部的修改后name变量值:", name)
    33     fmt.Println("person函数外部的name的内存地址:", &name)
    34     fmt.Println(person(&name, &age))
    35     fmt.Printf("person函数外部的修改后name变量值:%s 
    ",name)
    36 
    37     fmt.Println("--------------------------------------------")
    38     fmt.Println(swap(x,y ))
    39     fmt.Println("swap函数外部的x变量值:", x)
    40     fmt.Println("swap函数外部的y变量值:", y)
    41 
    42 }

    以上代码返回的运行结果:

    person函数内部的修改后name变量值: demon
    person函数外部的name的内存地址: 0xc42006e1a0
    person函数内部的name的内存地址: 0xc42006e1a0
    person函数内部的修改后name变量值:大佬
    person函数外部的修改后name变量值:大佬 
    --------------------------------------------
    swap函数内部的x变量值: 50
    swap函数内部的y变量值: 100
    
    swap函数外部的x变量值: 10
    swap函数外部的y变量值: 20
  • 相关阅读:
    [bzoj4942][noi2017]整数【线段树】
    面向对象的几个函数
    各种编码方式及其来历
    java nio中,HeapByteBuffer与DirectByteBuffer的区别
    volatile关键字的作用
    git常用命令
    关于git的一些零碎知识
    rm(操作系统的删除文件)与git rm的区别
    php的数组
    SQL Server中模式(schema)、数据库(database)、表(table)、用户(user)之间的关系
  • 原文地址:https://www.cnblogs.com/demon89/p/7258805.html
Copyright © 2011-2022 走看看