Go变量指针的实现示例

 更新时间:2025年09月26日 09:19:02   作者:Jayden_念旧  
Go指针存储变量地址,用于修改变量、避免拷贝、动态分配,本文就来详细的介绍一下Go变量指针的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在Go语言中,指针是一个存储变量内存地址的变量。通过指针,可以间接访问和操作原始数据。从而提高程序的效率,特别是在处理复杂数据结构或需要共享数据时。

概念说明
指针声明var p *int
取地址&a → 获取 a 的地址
解引用*p → 访问 p 指向的值
零值nil
主要用途修改变量、避免拷贝、动态分配

1.指针的本质

  • 指针是一种特殊变量,其值是另一个变量的内存地址
  • 通过指针可以间接访问或修改原始变量的值。

2.声明指针

语法:var ptr *Type

var a int = 10
var ptr *int // 声明一个指向 int 类型的指针
ptr = &a     // 将 a 的内存地址赋值给 ptr

3.关键操作符

  • &(取地址符):获取变量的内存地址。
ptr = &a // ptr 现在存储 a 的地址
  • *解引用符):访问指针指向的原始值。
  fmt.Println(*ptr) // 输出 10(通过 ptr 访问 a 的值)
  *ptr = 20         // 修改 a 的值为 20

4.指针的零值

  • 未初始化的指针值为 nil(表示无指向)。
var ptr *int // 初始值为 nil

5.指针的用途

  • 修改函数外部的变量
  func modify(val *int) {
      *val = 100
  }
  func main() {
      x := 10
      modify(&x) // x 被修改为 100
  }
  • 避免大对象拷贝:传递结构体指针而非整个结构体,减少内存开销。
  type Data struct { /* 大结构体 */ }
  func process(d *Data) { /* 操作 d */ }
  • 动态内存分配:与 new 或复合字面量一起使用。
  p := new(int) // 分配内存,返回指针
  *p = 42

6.指针示例

package main
 
import (
	"fmt"
)
 
type Person struct {
	Name    string
	Age     int
	Address string
	Salary  float64
}
 
func NewPerson(name string, age int, address string, salary float64) *Person {
	return &Person{Name: name, Age: age, Address: address, Salary: salary}
}
 
func main() {
	// 创建Person实例
	p := NewPerson("张三", 30, "北京市海淀区", 15000.50)
 
	// 访问字段
	fmt.Println(p.Name)   // 输出:张三
	fmt.Println(p.Salary) // 输出:15000.5
 
	// 修改字段值
	p.Age = 31
	p.Salary = 16000.00
}

为什么使用创建结构体指针:

1.内存效率优化

// 值类型返回(产生完整结构体拷贝)
func NewPerson() Person {
    return Person{...}
}

// 指针类型返回(仅传递内存地址)
func NewPerson() *Person {
    return &Person{...}
}
  • 结构体大小:当结构体包含多个字段(特别是包含大数组等)时,指针传递(通常 8 字节)比值拷贝更高效
  • 调用链损耗:在方法调用链中多次传递时,指针传递始终维持固定内存开销

2. 可变性控制

p := NewPerson("李四", 28, "上海", 25000)
p.Age = 29 // 直接修改原结构体

// 值类型接收者方法示例(无法修改原结构体)
func (p Person) SetAge(age int) {
    p.Age = age // 仅修改副本
}

// 指针类型接收者方法示例
func (p *Person) RealSetAge(age int) {
    p.Age = age // 修改原结构体
}
  • 指针接收者:通过返回指针,后续可以方便地定义指针接收者方法
  • 状态一致性:确保所有方法操作都作用于同一个内存对象

3. 零值有效性

// 错误处理扩展性
func NewPerson(age int) (*Person, error) {
    if age < 0 {
        return nil, errors.New("invalid age")
    }
    return &Person{Age: age}, nil
}
  • nil 语义:当构造函数需要实现错误处理时,指针类型可以直接返回 nil
  • 可选对象:调用方可通过 if p != nil 判断对象是否有效

7.注意!!!!!!!

  • 空指针(nil):解引用 nil 指针会导致运行时 panic。
  • 指针算术:Go 不支持指针算术(如 ptr++),除非使用 unsafe 包(不推荐)。
  • 值传递 vs 指针传递函数参数默认值传递,需用指针实现引用传递。

扩展:使用指针修改原始变量和通过函数修改的区别是什么

原理差异

  • 指针修改:在 Go 里,字符串是不可变类型,若要通过指针修改字符串,实际上修改的是存储字符串的字节切片。因为字符串底层由字节数组构成,借助指针操作可改变字节切片内容,再转换回字符串,从而更新原始变量。
  • strings.Builder 修改strings.Builder 内部维护一个字节切片,提供方法将字符串追加到该切片。当调用 String 方法时,会把内部字节切片转换为字符串返回。这种方式不会直接修改原始字符串,而是生成新字符串后重新赋值给原始变量。

代码实现差异

指针修改示例

package main
 
import (
    "fmt"
)
 
func modifyString(s *string) {
    bytes := []byte(*s)
    bytes = append(bytes, ' ', 'a', 'b', 'c')
    *s = string(bytes)
}
 
func main() {
    str := "this is a string"
    fmt.Println(&str)
    modifyString(&str)
    fmt.Println(str)
}

strings.Builder修改示例

package main
 
import (
	"fmt"
	"strings"
)
 
func main() {
	str := "this is a string"
	fmt.Println(&str)
	// 创建一个 strings.Builder 实例
	var builder strings.Builder
	// 将原始字符串写入 Builder
	builder.WriteString(str)
	// 在末尾添加 abc
	builder.WriteString(" abc")
	// 获取最终的字符串
	str = builder.String()
	fmt.Println(str)
}

性能差异

  • 指针修改:每次修改都要将字符串转换为字节切片,修改后再转换回字符串,频繁转换会带来额外内存分配和复制开销,性能欠佳。
  • strings.Builder 修改:内部维护字节切片,可动态扩容,减少内存分配次数,拼接字符串时性能更优,尤其在处理大量字符串拼接时优势明显。

使用场景差异

  • 指针修改:适用于需要直接操作原始变量内存地址,且修改操作较少的场景,或者希望通过函数修改外部变量的场景。
  • strings.Builder 修改适合需要频繁进行字符串拼接的场景,能有效提升性能。

到此这篇关于Go变量指针的实现示例的文章就介绍到这了,更多相关Go变量指针内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Go语言创建结构体实例对象的几种常用方式

    Go语言创建结构体实例对象的几种常用方式

    在Go语言中,创建结构体实例的几种方式有本质区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-11-11
  • GO env环境变量配置命令使用

    GO env环境变量配置命令使用

    这篇文章主要为大家介绍了GO env环境变量配置命令使用,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • golang三元表达式的使用方法

    golang三元表达式的使用方法

    这篇文章主要介绍了golang三元表达式的使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Go语言中GORM存取数组/自定义类型数据

    Go语言中GORM存取数组/自定义类型数据

    在使用gorm时往往默认的数据类型不满足我们的要求,需要使用一些自定义数据类型作为字段类型,下面这篇文章主要给大家介绍了关于Go语言中GORM存取数组/自定义类型数据的相关资料,需要的朋友可以参考下
    2023-01-01
  • k8s容器互联-flannel host-gw原理篇

    k8s容器互联-flannel host-gw原理篇

    这篇文章主要为大家介绍了k8s容器互联-flannel host-gw原理篇,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Go设计模式之中介者模式讲解和代码示例

    Go设计模式之中介者模式讲解和代码示例

    中介者是一种行为设计模式,让程序组件通过特殊的中介者对象进行间接沟通,达到减少组件之间依赖关系的目的,因此本文就给大家详细介绍一下Go中介者模式,需要的朋友可以参考下
    2023-06-06
  • web项目中golang性能监控解析

    web项目中golang性能监控解析

    这篇文章主要为大家介绍了web项目中golang性能监控详细的解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Kotlin编程基础语法编码规范

    Kotlin编程基础语法编码规范

    这篇文章主要为大家介绍了Kotlin编程条件控制示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • 基于Go语言实现Base62编码的三种方式以及对比分析

    基于Go语言实现Base62编码的三种方式以及对比分析

    Base62 编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,本文给大家介绍了Go语言实现Base62编码的三种方式以及对比分析,需要的朋友可以参考下
    2025-05-05
  • 让Go反射变快的方法实例探究

    让Go反射变快的方法实例探究

    反射允许你在运行时获得有关 Go 类型的信息,如果你曾经愚蠢地尝试编写 json.Unmarshal 之类的新版本,本文将探讨的就是如何使用反射来填充结构体值
    2024-01-01

最新评论