Golang深入浅出之-Go语言指针面试必知:理解与使用指针

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 【4月更文挑战第21天】Go语言中的指针允许直接操作内存,常用于高效数据共享和传递。本文介绍了指针的基础知识,如声明、初始化和解引用,以及作为函数参数使用。此外,讨论了`new()`与`make()`的区别和内存逃逸分析。在结构体上下文中,指针用于减少复制开销和直接修改对象。理解指针与内存管理、结构体的关系及常见易错点,对于面试和编写高性能Go代码至关重要。

指针是Go语言中一种重要的概念,它允许程序直接操作内存地址,从而实现高效的数据共享、修改和传递。在面试中,对指针的理解和使用能力往往是考察候选者Go语言功底的重要指标。本文将深入浅出地讲解Go语言指针的相关知识,包括基本概念、使用场景以及常见的问题与易错点,并通过代码示例加以阐述。
image.png

一、指针基础

指针声明与初始化

在Go语言中,声明一个指针类型变量需使用星号(*)标识:

var p *int // 声明一个指向整型变量的指针p

初始化指针时,为其赋予一个变量的内存地址:

i := 42
p = &i // 将变量i的地址赋给指针p

通过指针访问值

使用星号解引用指针以访问其指向的值:

fmt.Println(*p) // 输出:42

指针作为函数参数

通过指针传递参数,实现在函数内部修改原始变量的值:

func increment(ptr *int) {
   
   
    *ptr++
}

func main() {
   
   
    count := 10
    increment(&count)
    fmt.Println(count) // 输出:11
}

二、指针与内存管理

new()与make()

new()用于分配零值填充的内存块,并返回该内存块的地址(对应类型指针):

p := new(int) // 分配一个新的int类型的内存,初始值为0

make()用于创建切片、映射或通道等复合类型,返回的是已初始化的值而非指针:

s := make([]int, 5) // 创建长度为5的整型切片,初始元素均为0

内存逃逸分析

Go语言的垃圾回收机制会自动管理内存,但过度使用指针可能导致不必要的内存逃逸。理解并合理利用内存逃逸分析,能有效优化程序性能:

// 示例1:未发生逃逸
func createArray() [10]int {
   
   
    return [10]int{
   
   }
}

// 示例2:发生逃逸,因为返回的是指向堆内存的指针
func createSlice() *[]int {
   
   
    slice := make([]int, 10)
    return &slice
}

易错点:混淆new()make()的用法。牢记new()用于基本类型和自定义类型,返回指针;make()用于切片、映射和通道,返回初始化后的值。

三、指针与结构体

结构体指针

使用指针操作结构体可以减少复制开销,尤其在大型结构体或嵌套结构体中:

type Person struct {
   
   
    Name string
    Age  int
}

func updatePerson(p *Person) {
   
   
    p.Age++
}

func main() {
   
   
    person := Person{
   
   Name: "Alice", Age: 30}
    updatePerson(&person)
    fmt.Println(person) // 输出:{Alice 31}
}

指针接收者方法

结构体方法可以定义为接收者为指针类型,直接修改调用对象:

func (p *Person) incrementAge() {
   
   
    p.Age++
}

func main() {
   
   
    person := Person{
   
   Name: "Bob", Age: 40}
    person.incrementAge()
    fmt.Println(person) // 输出:{Bob 41}
}

易错点:在不需要修改结构体时仍使用指针接收者,可能导致不必要的内存分配。根据实际需求选择值类型或指针类型作为方法接收者。

总结,深入理解Go语言指针的概念、使用场景以及常见问题与易错点,是应对面试、编写高效Go代码的关键。通过练习上述代码示例,你将更好地掌握指针这一核心知识点,提升Go语言编程技能。在实际编程中,注意适时、合理地使用指针,避免内存泄漏、性能瓶颈等问题,提高代码质量和运行效率。

目录
相关文章
|
1月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
87 4
Golang语言之管道channel快速入门篇
|
1月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
56 4
Golang语言文件操作快速入门篇
|
1月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
76 3
Golang语言之gRPC程序设计示例
|
1月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
69 4
|
6天前
|
前端开发 中间件 Go
实践Golang语言N层应用架构
【10月更文挑战第2天】本文介绍了如何在Go语言中使用Gin框架实现N层体系结构,借鉴了J2EE平台的多层分布式应用程序模型。文章首先概述了N层体系结构的基本概念,接着详细列出了Go语言中对应的构件名称,包括前端框架(如Vue.js、React)、Gin的处理函数和中间件、依赖注入和配置管理、会话管理和ORM库(如gorm或ent)。最后,提供了具体的代码示例,展示了如何实现HTTP请求处理、会话管理和数据库操作。
21 0
|
1月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
41 4
Golang语言goroutine协程篇
|
1月前
|
Prometheus Cloud Native Go
Golang语言之Prometheus的日志模块使用案例
这篇文章是关于如何在Golang语言项目中使用Prometheus的日志模块的案例,包括源代码编写、编译和测试步骤。
35 3
Golang语言之Prometheus的日志模块使用案例
|
12天前
|
编译器 C语言
经典左旋,指针面试题
文章介绍了两种C语言实现字符串左旋的方法,以及如何使用C语言对整数数组进行奇偶数排序。通过实例演示了如何使用函数reverse_part和leftRound,以及在swap_arr中实现数组元素的重新排列。
24 0
|
19天前
|
Serverless 编译器 C语言
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
【C语言】指针篇- 深度解析Sizeof和Strlen:热门面试题探究(5/5)
|
1月前
|
JSON Go 数据格式
Golang语言结构体链式编程与JSON序列化
这篇文章是关于Go语言中结构体链式编程与JSON序列化的教程,详细介绍了JSON格式的基本概念、结构体的序列化与反序列化、结构体标签的使用以及如何实现链式编程。
30 4