0

0

深入理解Go语言中的指针:解密星号()和取地址符(&)

聖光之護

聖光之護

发布时间:2025-07-17 21:02:02

|

240人浏览过

|

来源于php中文网

原创

深入理解Go语言中的指针:解密星号()和取地址符(&)

本文旨在深入解析Go语言中星号()和取地址符(&)的关键作用。星号(*)用于声明指针类型、解引用指针以访问其指向的值,以及通过指针进行间接赋值。取地址符(&)则用于获取变量的内存地址,从而创建指向该变量的指针。通过具体示例,读者将全面掌握Go语言中指针的声明、使用及操作,为编写高效、灵活的Go程序奠定基础。

Go语言中的指针概述

go语言中,指针是一种特殊类型的变量,它存储的是另一个变量的内存地址。通过指针,我们可以间接地访问或修改存储在特定内存地址中的值。理解指针对于编写高效、能够直接操作内存的go程序至关重要,尤其是在需要修改函数参数的原始值或传递大型数据结构时。

星号 * 的多重含义

星号(*)在Go语言中扮演着多重角色,其具体含义取决于它在代码中的上下文。

1. 指针类型声明 (*Type)

当星号紧跟在类型名称之前时(例如 *int、*string),它表示声明一个指向该类型值的指针变量。这意味着该变量将存储一个特定类型值的内存地址。

示例:

萝卜简历
萝卜简历

免费在线AI简历制作工具,帮助求职者轻松完成简历制作。

下载
var ptr *int // 声明一个名为 ptr 的变量,它是一个指向 int 类型值的指针
var namePtr *string // 声明一个指向 string 类型值的指针

2. 指针解引用 (*variable)

当星号放置在一个已声明的指针变量前面时(例如 *ptr),它表示对该指针进行“解引用”操作。解引用是指访问该指针所指向的内存地址中存储的实际值。

立即学习go语言免费学习笔记(深入)”;

示例:

num := 10
ptr := &num // ptr 存储 num 的地址
value := *ptr // 解引用 ptr,获取 num 的值 (即 10)
fmt.Println(value) // 输出: 10

3. 指针间接赋值 (*variable = value)

同样地,当星号放置在一个指针变量前面,并用于赋值操作的左侧时(例如 *ptr = newValue),它表示通过该指针间接修改其所指向的内存地址中的值。这会直接影响到原始变量的值。

示例:

num := 10
ptr := &num // ptr 存储 num 的地址
fmt.Println("修改前 num 的值:", num) // 输出: 10
*ptr = 20 // 通过 ptr 间接修改 num 的值
fmt.Println("修改后 num 的值:", num) // 输出: 20

取地址符 & 的作用

取地址符(&)用于获取一个变量的内存地址。当 & 放置在一个变量前面时,它会返回一个指向该变量内存地址的指针。

示例:

age := 30
agePtr := &age // agePtr 获取变量 age 的内存地址,并成为一个指向 int 类型的指针
fmt.Printf("age 的值: %d, age 的地址: %p\n", age, agePtr)
// 输出示例: age 的值: 30, age 的地址: 0xc0000140a8 (地址会因运行环境而异)

综合示例与解析

为了更好地理解 * 和 & 的协同工作,我们来看一个综合性的代码示例:

package main

import (
    "fmt"
)

func main() {
    // 1. 声明并初始化一个字符串变量 s
    s := "hello"
    fmt.Printf("s 初始值: \"%s\", 地址: %p\n", s, &s)
    // 此时 s 的值是 "hello",&s 获取 s 变量在内存中的地址。

    // 2. 修改 s 的值
    s = "good bye"
    fmt.Printf("s 修改后值: \"%s\", 地址: %p\n", s, &s)
    // s 的值被直接修改为 "good bye",但它的内存地址保持不变。

    // 3. 声明一个字符串指针 p,并将其指向 s 的地址
    var p *string = &s
    fmt.Printf("p 的值 (s 的地址): %p, p 指向的值: \"%s\"\n", p, *p)
    // var p *string 声明 p 是一个指向字符串的指针。
    // &s 获取 s 的内存地址,并将其赋值给 p。
    // 此时 p 存储的是 s 的地址,*p 则解引用 p,获取 s 的当前值 "good bye"。

    // 4. 通过指针 p 间接修改 s 的值
    *p = "ciao"
    fmt.Printf("通过 p 修改后 s 的值: \"%s\", 地址: %p\n", s, &s)
    fmt.Printf("p 的值 (s 的地址): %p, p 指向的值: \"%s\"\n", p, *p)
    // *p = "ciao" 表示通过 p 所指向的内存地址,将该地址处的值修改为 "ciao"。
    // 因为 p 指向的是 s 的地址,所以 s 的值也随之变成了 "ciao"。
    // 此时 s 的值和 *p 的值都变成了 "ciao",而它们的地址保持不变。
}

运行结果示例:

s 初始值: "hello", 地址: 0xc000010200
s 修改后值: "good bye", 地址: 0xc000010200
p 的值 (s 的地址): 0xc000010200, p 指向的值: "good bye"
通过 p 修改后 s 的值: "ciao", 地址: 0xc000010200
p 的值 (s 的地址): 0xc000010200, p 指向的值: "ciao"

从输出可以看出,s 的地址在整个过程中保持不变,而 p 始终存储着 s 的地址。对 *p 的赋值操作直接改变了 s 的值,这充分体现了指针通过地址间接操作数据的能力。

注意事项与最佳实践

  1. 零值指针 (nil): 未初始化的指针变量的默认值为 nil。尝试解引用一个 nil 指针(例如 *nilPtr)会导致运行时 panic。在操作指针前,务必检查其是否为 nil,尤其是在从函数返回指针时。

    var nilPtr *int
    if nilPtr == nil {
        fmt.Println("nilPtr 是 nil")
    }
    // fmt.Println(*nilPtr) // 这行代码会导致运行时错误 (panic)
  2. Go语言中没有指针算术: 与C/C++不同,Go语言不允许对指针进行算术运算(如 ptr++ 或 ptr + offset)。这种设计减少了内存操作的复杂性,提高了安全性。

  3. 何时使用指针

    • 修改函数参数的原始值:当函数需要修改其调用者传入的变量时,必须通过指针传递。Go语言函数参数默认是按值传递的。
    • 传递大型数据结构:对于大型的结构体(struct)、数组等,按值传递会产生复制开销。通过传递它们的指针,可以避免不必要的内存复制,提高性能。
    • 实现特定数据结构:链表、树等依赖于节点间引用关系的数据结构需要使用指针来实现。
    • 表示可选字段或缺失值:在某些场景下,指针可以用来区分一个字段是未设置(nil)还是设置为零值(例如 0 或 "")。
  4. 避免不必要的指针: 对于小型、值语义的数据类型(如 int、bool、string 等),通常直接按值传递更清晰、更安全,因为它们复制的开销很小。过度使用指针会增加代码的复杂性,并可能引入 nil 指针解引用等问题。

总结

星号(*)和取地址符(&)是Go语言中处理指针的核心操作符。* 用于声明指针类型、解引用指针以获取其指向的值,以及通过指针进行间接赋值;& 则用于获取变量的内存地址,从而创建指向该变量的指针。掌握这些概念是理解Go语言内存管理、编写高效且灵活程序的基础。正确地使用指针能够优化程序性能,实现更复杂的数据结构和编程模式,但同时也需要注意避免 nil 指针等常见陷阱。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

307

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

358

2023.08.02

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

198

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

190

2025.07.04

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

198

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

190

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

358

2023.08.02

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Rust 教程
Rust 教程

共28课时 | 4.8万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 2.8万人学习

Go 教程
Go 教程

共32课时 | 4.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号