Bruce Blog Bruce Blog
首页
  • CentOS
  • Ubuntu-Debian
  • 系统网络
  • 系统辅助工具
  • MySQL
  • Redis
  • Mongodb
  • Docker基础
  • Container基础
  • Kubernetes

    • Kubernetes基础
    • Kubernetes辅助
  • Container-Network
  • Jenkins
  • Gitlab
  • ArgoCD
  • Ansible
  • Terraform
  • AWS
  • MQ
  • NGINX
  • JumpServer
  • 基础
  • 函数模块
  • 框架
  • 基础

    • Golang环境
    • 语法
    • 数据类型与运算符
    • 分支语句
    • 循环语句
    • 数组
    • 切片
    • Map
    • String
    • 函数
    • 包的管理
    • 指针
    • 结构体
    • Go语言中的OOP
    • 方法和接口
    • 错误处理
  • Go进阶

    • Go进阶
  • Go框架

    • Go框架
  • Golang辅助

    • Golang辅助
  • CSS
  • HTML
  • JavaScript
  • 前端辅助
  • 常用命令
  • 性能监控工具
  • Windows下Docker使用
  • 日常学习
  • 其他导航

Bruce Tao

运维界的该溜子
首页
  • CentOS
  • Ubuntu-Debian
  • 系统网络
  • 系统辅助工具
  • MySQL
  • Redis
  • Mongodb
  • Docker基础
  • Container基础
  • Kubernetes

    • Kubernetes基础
    • Kubernetes辅助
  • Container-Network
  • Jenkins
  • Gitlab
  • ArgoCD
  • Ansible
  • Terraform
  • AWS
  • MQ
  • NGINX
  • JumpServer
  • 基础
  • 函数模块
  • 框架
  • 基础

    • Golang环境
    • 语法
    • 数据类型与运算符
    • 分支语句
    • 循环语句
    • 数组
    • 切片
    • Map
    • String
    • 函数
    • 包的管理
    • 指针
    • 结构体
    • Go语言中的OOP
    • 方法和接口
    • 错误处理
  • Go进阶

    • Go进阶
  • Go框架

    • Go框架
  • Golang辅助

    • Golang辅助
  • CSS
  • HTML
  • JavaScript
  • 前端辅助
  • 常用命令
  • 性能监控工具
  • Windows下Docker使用
  • 日常学习
  • 其他导航
  • 基础

    • Golang环境

    • 语法

    • 数据类型与运算符

    • 分支语句

    • 循环语句

    • 数组

    • 切片

    • Map

    • String

    • 函数

    • 包的管理

    • 指针

      • 指针
      • 指针的使用
      • 结构体

      • Go语言中的OOP

      • 方法和接口

      • 错误处理

    • Go进阶

    • Go框架

    • Golang辅助

    • Golang
    • 基础
    • 指针
    Bruce
    2022-10-27
    目录

    指针的使用

    # 一、指针

    # 1.1 指针的概念

    • 指针是存储另一个变量的内存地址的变量.
    • 都知道,变量是一种使用方便的占位符,用于引用计算机内存地址.
    • 一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址.

    image-20220904215821758

    上图中,变量b的值为156,存储在内存地址0x1040a124.变量a持有b的地址,现在a被认为指向b.

    # 1.2 获取变量的地址

    • Go语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址.
    package main
    
    import "fmt"
    
    func main() {
       var a int = 10   
    
       fmt.Printf("变量的地址: %x\n", &a  )
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    运行结果:

    变量的地址: 20818a220
    
    1

    # 1.3 声明指针

    • 声明指针,*T是指针变量的类型,它指向T类型的值.
    var var_name *var-type
    
    1

    var-type为指针类型,var_name为指针变量名,*号用于指定变量是作为一个指针.

    var ip *int        /* 指向整型*/
    var fp *float32    /* 指向浮点型 */
    
    1
    2

    示例代码:

    package main
    
    import "fmt"
    
    func main() {
       var a int= 20   /* 声明实际变量 */
       var ip *int        /* 声明指针变量 */
    
       ip = &a  /* 指针变量的存储地址 */
    
       fmt.Printf("a 变量的地址是: %x\n", &a  )
    
       /* 指针变量的存储地址 */
       fmt.Printf("ip 变量的存储地址: %x\n", ip )
    
       /* 使用指针访问值 */
       fmt.Printf("*ip 变量的值: %d\n", *ip )
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    运行结果:

    a 变量的地址是: 20818a220
    ip 变量的存储地址: 20818a220
    *ip 变量的值: 20
    
    1
    2
    3

    示例代码:

    package main
    
    import "fmt"
    
    type name int8
    type first struct {
    	a int
    	b bool
    	name
    }
    
    func main() {
    	a := new(first)
    	a.a = 1
    	a.name = 11
    	fmt.Println(a.b, a.a, a.name)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    运行结果:

    false 1 11
    
    1

    未初始化的变量自动赋上初始值

    package main
    
    import "fmt"
    
    type name int8
    type first struct {
    	a int
    	b bool
    	name
    }
    
    func main() {
    	var a = first{1, false, 2}
    	var b *first = &a
    	fmt.Println(a.b, a.a, a.name, &a, b.a, &b, (*b).a)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    运行结果:

    false 1 2 &{1 false 2} 1 0xc042068018 1
    
    1

    获取指针地址在指针变量前加&的方式

    # 1.4 空指针

    # Go 空指针
    • 当一个指针被定义后没有分配到任何变量时,它的值为nil.
    • nil指针也称为空指针.
    • nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值.
    • 一个指针变量通常缩写为ptr.

    空指针判断:

    if(ptr != nil)     /* ptr 不是空指针 */
    if(ptr == nil)    /* ptr 是空指针 */
    
    1
    2

    # 1.5 获取指针的值

    • 获取一个指针意味着访问指针指向的变量的值.语法是:*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)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

    # 1.6 操作指针改变变量的数值

    示例代码:

    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++  // 这里的`++`是加`1`
        fmt.Println("new value of b is", b)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    运行结果

    address of b is 0x1040a124  
    value of b is 255  
    new value of b is 256  
    
    1
    2
    3

    # 1.7 使用指针传递函数的参数

    示例代码

    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)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    运行结果

    value of a before function call is 58  
    value of a after function call is 55  
    
    1
    2

    不要将一个指向数组的指针传递给函数.使用切片.

    假设想对函数内的数组进行一些修改,并且对调用者可以看到函数内的数组所做的更改.一种方法是将一个指向数组的指针传递给函数.

    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)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    运行结果

    [90 90 91]
    
    1

    示例代码:

    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)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    运行结果

    [90 90 91]
    
    1

    虽然将指针传递给一个数组作为函数的参数并对其进行修改,但这并不是实现这一目标的惯用方法.还有切片.

    示例代码:

    package main
    
    import (  
        "fmt"
    )
    
    func modify(sls []int) {  
        sls[0] = 90
    }
    
    func main() {  
        a := [3]int{89, 90, 91}
        modify(a[:])
        fmt.Println(a)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    运行结果:

    [90 90 91]
    
    1
    • Go不支持指针算法.
    package main
    
    func main() {  
    b := [...]int{109, 110, 111}
    p := &b
    p++
    }
    
    nvalid operation: p++ (non-numeric type *[3]int)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 指针数组
    package main
    
    import "fmt"
    
    const MAX int = 3
    
    func main() {
    
       a := []int{10,100,200}
       var i int
    
       for i = 0; i < MAX; i++ {
          fmt.Printf("a[%d] = %d\n", i, a[i] )
       }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    结果

    a[0] = 10
    a[1] = 100
    a[2] = 200
    
    1
    2
    3
    • 有一种情况,可能需要保存数组,这样就需要使用到指针.
    package main
    
    import "fmt"
    
    const MAX int = 3
    
    func main() {
       a := []int{10,100,200}
       var i int
       var ptr [MAX]*int;
    
       for  i = 0; i < MAX; i++ {
          ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
       }
    
       for  i = 0; i < MAX; i++ {
          fmt.Printf("a[%d] = %d\n", i,*ptr[i] )
       }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    结果

    a[0] = 10
    a[1] = 100
    a[2] = 200
    
    1
    2
    3
    # 数组指针和指针数组
    package main
    
    import "fmt"
    
    func main() {
    	/*
    		数组指针: 首先是一个指针,一个数组的地址
    			*[4]Type
    
    		指针数组: 首先是一个数组,存储的数据类型是指针.
    			[4]*Type
    
    			*[5]float64,指针,一个存储了5个浮点类型数据的数组指针
    			*[3]string,指针,数组的指针,存储了3个字符串
    			[3]*string,数组,存储了3个字符串的指针地址的数组
    			[5]*float64,数组,存储了5个浮点数的地址的数组
    			*[5]*float64,指针,一个数组的指针,存储了5个float类型的数据的指针地址的数组的指针
    			*[3]*string,指针,存储了3个字符串的指针地址的数据指针
    			**[4]string,指针,存储了4个字符串数据的数组的指针的指针
    			**[4]*string,指针,存储了4个字符串的指针地址的数组的指针的指针
    	*/
    	//1.创建一个普通数组
    	arr1 := [4]int{1, 2, 3, 4}
    	fmt.Println(arr1)
    
    	//2出AG你就按一个指针,存储该数组的地址--->数组指针
    	var p1 *[4]int
    	p1 = &arr1
    	fmt.Println(p1)         // &[1 2 3 4],打印的是arr1的指针
    	fmt.Printf("%p\n", p1)  //数组arr1的地址
    	fmt.Printf("%p\n", &p1) //p1指针自己的地址
    
    	//3.根据属猪指针,操作数组
    	(*p1)[0] = 100
    	fmt.Println(arr1)
    
    	p1[0] = 200 // 简化写法
    	fmt.Println(arr1)
    
    	//4.指针数组
    	a := 1
    	b := 2
    	c := 3
    	d := 4
    	arr2 := [4]int{a, b, c, d}
    	arr3 := [4]*int{&a, &b, &c, &d}
    	fmt.Println(arr2)
    	fmt.Println(arr3)
    
    	arr2[0] = 100
    	fmt.Println(arr2)
    	fmt.Println(a)
    
    	*arr3[0] = 200
    	fmt.Println(arr3)
    	fmt.Println(a)
    
    	b = 1000
    	fmt.Println(arr2)
    	fmt.Println(arr3)
    	for i := 0; i < len(arr3); i++ {
    		fmt.Println(*arr3[i])
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64

    # 1.8 指针的指针

    # 指针的指针
    • 如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量.
    var ptr **int;
    
    1
    package main
    
    import "fmt"
    
    func main() {
    
       var a int
       var ptr *int
       var pptr **int
    
       a = 3000
    
       /* 指针 ptr 地址 */
       ptr = &a
    
       /* 指向指针 ptr 地址 */
       pptr = &ptr
    
       /* 获取 pptr 的值 */
       fmt.Printf("变量 a = %d\n", a )
       fmt.Printf("指针变量 *ptr = %d\n", *ptr )
       fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    结果

    变量 a = 3000
    指针变量 *ptr = 3000
    指向指针的指针变量 **pptr = 3000
    
    1
    2
    3
    # 指针作为函数参数
    package main
    
    import "fmt"
    
    func main() {
       /* 定义局部变量 */
       var a int = 100
       var b int= 200
    
       fmt.Printf("交换前 a 的值 : %d\n", a )
       fmt.Printf("交换前 b 的值 : %d\n", b )
       fmt.Println("======================")
       /* 调用函数用于交换值
       * &a 指向 a 变量的地址
       * &b 指向 b 变量的地址
       */
       swap(&a, &b);
       fmt.Printf("交换后 a 的值 : %d\n", a )
       fmt.Printf("交换后 b 的值 : %d\n", b )
    }
    
    func swap(x *int, y *int) {
       var temp int
       temp = *x    /* 保存 x 地址的值 */
       *x = *y      /* 将 y 赋值给 x */
       *y = temp    /* 将 temp 赋值给 y */
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    结果

    交换前 a 的值 : 100
    交换前 b 的值 : 200
    交换后 a 的值 : 200
    交换后 b 的值 : 100
    
    1
    2
    3
    4
    # 函数指针和指针函数
    package main
    
    import "fmt"
    
    func main() {
    	/*
    		函数指针: 一个指针,指向了一个函数的指针.
    			因为go语言中,function,默认看作一个指针,没有*
    
    		指针函数: 一个函数,该函数的返回值是一个指针.
    	*/
    	var a func()
    	a = fun1
    	a()
    
    	arr1 := fun2()
    	fmt.Printf("arr1的类型: %T,地址: %p,数值: %v\n", arr1, &arr1, arr1)
    
    	arr2 := fun3()
    	fmt.Printf("arr2的类型: %T,地址: %p,数值: %v\n", arr2, &arr2, arr2)
    	fmt.Printf("arr2指针中存储的数组的地址: %p\n", arr2)
    }
    
    func fun3() *[4]int {
    	arr := [4]int{1, 2, 3, 4}
    	fmt.Printf("函数中arr的地址: %p\n", &arr)
    	return &arr
    }
    
    func fun2() [4]int { //普通函数
    	arr := [4]int{1, 2, 3, 4}
    	return arr
    }
    
    func fun1() {
    	fmt.Println("fun1()......")
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37

    # 1.9.综合示例代码

    package main
    
    import "fmt"
    
    func main() {
    	/*
    		指针: pointer
    			存储了另一个变量的内存地址的变量.
    	*/
    	//1.定义一个int类型的变量
    	a := 10
    	fmt.Println("a的数值是: ", a)
    	fmt.Printf("%T\n", a)
    	fmt.Printf("a的地址是: %p\n", &a)
    
    	//2.创建一个指针变量,用于存储变量a的地址
    	var p1 *int
    	fmt.Println(p1) // <nil> 空指针
    	p1 = &a
    	fmt.Println("p1的数值", p1) // p1中存储a的地址地址
    	fmt.Printf("p1自己的地址: %p\n", &p1)
    	fmt.Println("p1的数值,是a的地址,该地址存储的数据: ", *p1) // 获取指针指向的变量的数值
    
    	//3.操作变量,修改数值;并不会改变地址
    	a = 100
    	fmt.Println(a)
    	fmt.Printf("%p\n", &a)
    
    	//4.通过指针,改变变量的数值
    	*p1 = 200
    	fmt.Println(a)
    
    	//5.指针的指针
    	var p2 **int
    	fmt.Println(p2)
    	p2 = &p1
    	fmt.Printf("%T,%T,%T\n", a, p1, p2) // int,*int,**int
    	fmt.Println("p2的数值: ", p2)
    	fmt.Println("p2的地址: ", &p2)
    	fmt.Println("p2中存储的地址,赌赢的数值,就是p1的地址,对应的数据: ", *p2)
    	fmt.Println("p2存储的地址,对应的数值,在获取对应的数值: ", **p2)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    上次更新: 2024/04/09, 16:48:42
    指针
    结构体

    ← 指针 结构体→

    最近更新
    01
    AWS NAT-NetWork-Firwalld配置(一)
    04-09
    02
    AWS NAT-NetWork-Firwalld配置(二)
    04-09
    03
    kubernetes部署minio对象存储
    01-18
    更多文章>
    Theme by Vdoing | Copyright © 2019-2024 Bruce Tao Blog Space | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式