3.指针

指针

任何指针的零值都是 nil

1. 基础内容

1.1. 指针的基本用法

指针不能运算,Go 语言只有值传递一种方式,引用类型,也会拷贝引用的地址

1
2
3
4
var a int = 2
var pa *int = &a
*pa = 3
fmt.Println(a)

1.2. 指针相等的条件

  • 都是 nil
  • 指向同一个变量

在 Go 语言中,返回函数中局部变量的地址也是安全的

1.3.new 预定义函数

new(T) 将创建一个 T 类型的匿名变量,初始化T 类型零值,返回变量地址,类型是 *T

new 是预定义函数,并非关键字,可以更改类型,声明为变量等操作,但不建议这样干!

1
2
3
4
p := new(int)   // p, *int 类型, 指向匿名的 int 变量
fmt.Println(*p) // "0"
*p = 2          // 设置 int 匿名变量的值为 2
fmt.Println(*p) // "2"

struct{}[0]int是大小为 0 的类型,(请谨慎使用大小为0的类型,因为这样可能会导致Go语言的自动垃圾回收器有不同的行为,具体请查看runtime.SetFinalizer函数相关文档)。

1.4.变量的生命周期

包级别的变量,生命周期和程序的运行周期一致

函数的参数和返回值都是局部变量,在函数被调用的时候创建,函数的生命周期(栈帧)结束销毁

Golang 语言的自动垃圾回收,这里避开实现细节,说一下思路 :

从每个包级的变量和每个当前运行函数的每一个局部变量开始,通过指针或引用的访问路径遍历,是否可以找到该变量。如果不存在这样的访问路径,那么说明该变量是不可达的,也就是说它是否存在并不会影响程序后续的计算结果。

因为一个变量的有效周期只取决于是否可达,因此一个循环迭代内部的局部变量的生命周期可能超出其局部作用域。同时,局部变量可能在函数返回之后依然存在。

编译器会自动选择在栈上还是在堆上分配局部变量的存储空间,选择并不是由用var还是new声明变量的方式决定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var global *int

func f() {
    var x int
    x = 1
    global = &x     // 堆上, 因为包级别还在引用, 从 f 函数中逃逸了
}

func g() {
    y := new(int)   // 外部没有引用, 编辑器可以选择栈或堆上分配,
    *y = 1
}

其实在任何时候,你并不需为了编写正确的代码而要考虑变量的逃逸行为,要记住的是,逃逸的变量需要额外分配内存,同时对性能的优化可能会产生细微的影响。

如果将指向短生命周期对象的指针保存到具有长生命周期的对象中,特别是保存到全局变量时,会阻止对短生命周期对象的垃圾回收(从而可能影响程序的性能)。

2. 使用案例

2.1. 使用指针实现 Echo 命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Echo4 prints its command-line arguments.
package main

import (
    "flag"
    "fmt"
    "strings"
)

// 创建布尔变量 , 参数 : 命令行参数,默认值,描述信息
var n = flag.Bool("n", false, "omit trailing newline")
var sep = flag.String("s", " ", "separator")

func main() {
    // 获取参数之前必须解析
    flag.Parse()
  // flag.Args() 普通命令行参数
    fmt.Print(strings.Join(flag.Args(), *sep))
    if !*n {
        fmt.Println()
    }
}

2.2. 使用指针来交换变量

1
2
3
4
5
6
7
8
9
func swap(a,b *int){
  *a,*b = *b,*a
}

func main(){
  var a,b int = 2,4
  swap(&a,&b)
  fmt.Println(a,b)
}
1
2
var a *int
unsafe.Sizeof(a)    // 对指针求大小, 64位系统=8 
  • 要改变内容必须使用指针接收者
  • 结构过大也考虑使用指针接收者( 避免大量拷贝浪费性能 )
  • 一致性: 如有指针接收者, 都使用指针接收者 ( 纯属为方便 )
Licensed under CC BY-NC-SA 4.0
本文阅读量 次, 总访问量 ,总访客数
Built with Hugo .   Theme Stack designed by Jimmy