关于go:Go指针探秘深入理解内存与安全性

32次阅读

共计 3735 个字符,预计需要花费 10 分钟才能阅读完成。

Go 指针为程序员提供了对内存的深刻治理能力,同时确保了代码的安全性。本文深入探讨了 Go 指针的根底概念、操作、深层了解及其个性与限度。通过深刻理解其设计哲学和利用,咱们能够更好地利用 Go 的弱小性能。

关注公众号【TechLeadCloud】,分享互联网架构、云服务技术的全维度常识。作者领有 10+ 年互联网服务架构、AI 产品研发教训、团队治理教训,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收 AI 产品研发负责人。

1. 指针的根底

1.1 什么是指针?

指针是一种变量,其存储的是另一个变量的内存地址,而不是值自身。在很多编程语言中,当咱们须要间接拜访内存或者心愿通过一个变量间接操作另一个变量时,会应用到指针。

示例:

var a int = 42
var p *int = &a
fmt.Println(p) // 打印变量 a 的内存地址

1.2 内存地址与值的地址

每一个变量都存储在内存中的一个地位上,这个地位被称为该变量的内存地址。而当咱们议论一个变量的地址时,咱们实际上是在探讨这个内存地址。

1.2.1 内存中的数据存储

计算机的内存是依照字节(bytes)组织的,每个字节都有一个惟一的地址。一个变量占用的字节数取决于其类型,例如,一个 int 类型在 64 位零碎上通常是 8 字节。

示例:

var x int64 = 123456789
fmt.Println(&x) // 打印变量 x 的内存地址

1.2.2 如何了解值的地址

当咱们应用 & 操作符来获取一个变量的地址时,咱们实际上获取的是指向该变量内存起始地位的指针。

示例:

var y string = "OpenAI"
fmt.Println(&y) // 打印变量 y 的内存地址

在下面的示例中,变量 y 存储了字符串 ”OpenAI”,但 &y 给咱们返回的是这个字符串存储在内存中的地址。


2. Go 中的指针操作

2.1 指针类型和值

在 Go 中,每种数据类型都有与之关联的指针类型。指针类型的定义是前置一个 * 到原始数据类型后面。例如,int的指针类型是*int

2.1.1 根本数据类型的指针

示例:

var age int = 30
var agePointer *int = &age

fmt.Println(age)        // 打印原始变量值:30
fmt.Println(agePointer) // 打印 age 变量的内存地址

2.1.2 复合数据类型的指针

Go 中的复合数据类型(例如 slices、maps、channels、arrays、structs)也有其对应的指针类型。

示例:

type Person struct {
    Name string
    Age  int
}

var person Person = Person{"Alice", 28}
var personPointer *Person = &person

fmt.Println(person)          // 打印构造体值:{Alice 28}
fmt.Println(personPointer)   // 打印构造体的内存地址

2.2 如何获取一个指针值

要获取一个变量的指针值,能够应用 & 操作符。

示例:

var fruit string = "apple"
pointerToFruit := &fruit

fmt.Println(fruit)           // 打印原始值:apple
fmt.Println(pointerToFruit)  // 打印 fruit 的内存地址

2.3 指针(地址)解援用

要获取指针指向的原始值,咱们应用 * 操作符进行解援用。这容许咱们间接地拜访和批改指针指向的值。

示例:

var number int = 100
pointerToNumber := &number

fmt.Println(*pointerToNumber) // 通过解援用获取原始值:100

// 批改指针指向的值
*pointerToNumber = 200
fmt.Println(number)           // 原始变量值被批改为:200

3. 深刻了解指针

3.1 咱们为什么须要指针?

指针在编程中是一个重要的工具,特地是在须要高性能、灵活性或者对内存应用有严格要求的场景中。

3.1.1 进步程序性能

指针能够缩小数据复制的须要,从而进步程序的执行速度。

示例:

思考一个场景,咱们须要替换两个大的数据结构的值。

type LargeStruct struct {Data [1000]int
}

func swapWithoutPointer(a, b LargeStruct) {a, b = b, a}

func swapWithPointer(a, b *LargeStruct) {*a, *b = *b, *a}

var x, y LargeStruct
// 应用指针替换
swapWithPointer(&x, &y)

在下面的例子中,应用指针的办法能够防止复制两次大的数据结构,从而更为高效。

3.1.2 动静数据结构

很多动静数据结构(如链表、树、图)都依赖于指针来实现。

示例:

type Node struct {
    Value int
    Next  *Node
}

// 创立链表
first := Node{Value: 1}
second := Node{Value: 2}
third := Node{Value: 3}

first.Next = &second
second.Next = &third

fmt.Println(first.Value)  // 1
fmt.Println(first.Next.Value) // 2

3.1.3 与其余语言的比拟

与其余一些语言(如 C、C++)相比,Go 在指针的应用上更为平安。Go 不容许进行指针运算,这升高了因为错误操作而导致的程序谬误的可能性。

3.2 对于 ” 援用 ” 这个术语

在其余一些编程语言中(如 C ++、Java),” 援用 ” 与 ” 指针 ” 是两个不同的概念,但在 Go 中,咱们次要应用指针,而不是援用。

3.2.1 援用与指针的区别

在某些语言中,援用是一个别名,它示意某个变量。而指针则是一个变量,其值是另一个变量的地址。

示例: 在 Go 中,咱们不应用援用,而是应用指针来实现间接援用。

var original int = 10
pointerToOriginal := &original

*pointerToOriginal = 20

fmt.Println(original) // 输入:20

在上述示例中,通过指针,咱们批改了 original 变量的值。


4. Go 指针的个性与限度

4.1 Go 指针的个性

4.1.1 零值

在 Go 中,指针的零值是nil。这意味着如果你申明一个指针变量但没有明确初始化,它的值就是nil

示例:

var ptr *int
fmt.Println(ptr == nil) // 输入:true

4.1.2 不反对指针算术

与 C 和 C ++ 不同,Go 不反对指针算术操作。这是为了确保更高的内存安全性。

示例:

在 C 或 C ++ 中,你能够做这样的操作:

int arr[10];
int *ptr = &arr[0];
ptr++;

但在 Go 中,相似的操作是不被容许的。

arr := [10]int{}
ptr := &arr[0]
// ptr++ // 这行会报错,因为 Go 不反对

4.2 Go 指针的限度

4.2.1 不反对指针到整数的转换

在某些低级编程环境中,你可能须要将指针转换为整数进行某些操作,或者反之。但在 Go 中,这样的操作是不容许的,以确保程序的安全性和可读性。

4.2.2 不能获取内建数据类型的地址

在 Go 中,例如对于切片的元素或 map 的值,咱们不能间接获取其地址。

示例:

m := map[string]int{"Alice": 25}
// ptr := &m["Alice"] // 这行会报错

4.2.3 安全性

Go 的设计者们成心限度了指针的某些能力,以进步程序的安全性。例如,你不能在 Go 中进行指针算术,也不能随便地将指针与整数之间进行转换。


5. 总结

Go 语言为古代编程提供了一种独特的路径。它不仅联合了经典的 C 格调语法,还引入了一系列新鲜的设计哲学。这其中,Go 对指针的解决尤为杰出,它既保护了指针的功能性,又加强了代码的安全性。

深刻的内存治理: Go 语言通过指针让开发者有机会深刻理解和治理内存。与间接操作值相比,指针为数据操作带来了更大的灵活性,特地是在解决大型数据结构或心愿防止数据复制时。

安全性与简洁性的衡量: 通过打消指针算术和严格的类型限度,Go 确保了程序员在操作指针时的安全性。这种设计抉择可能限度了某些低级操作的能力,但它大大降低了因为误用指针而导致的程序谬误的危险。

高级与低级的联合: 只管 Go 提供了高级的数据结构如切片、映射等,但它依然容许程序员通过指针进行低级的内存操作。这为开发者提供了无可比拟的灵活性,使他们既能够编写高性能的代码,又不失代码的可读性和可维护性。

关注公众号【TechLeadCloud】,分享互联网架构、云服务技术的全维度常识。作者领有 10+ 年互联网服务架构、AI 产品研发教训、团队治理教训,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收 AI 产品研发负责人。

如有帮忙,请多关注
集体微信公众号:【TechLeadCloud】分享 AI 与云服务研发的全维度常识,谈谈我作为 TechLead 对技术的独特洞察。
TeahLead KrisChang,10+ 年的互联网和人工智能从业教训,10 年 + 技术和业务团队治理教训,同济软件工程本科,复旦工程治理硕士,阿里云认证云服务资深架构师,上亿营收 AI 产品业务负责人。

正文完
 0