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

 更新时间:2025年11月05日 09:56:48   作者:比特森林探险记  
在Go语言中,创建结构体实例的几种方式有本质区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在 Go 语言中,创建结构体实例的几种方式有本质区别。以下是核心差异的详细对比:

1. 内存分配与类型差异

​创建方式​​内存位置​​变量类型​​是否可被GC回收​
p := Person{...}通常栈空间值类型❌(栈自动释放)
p := new(Person)堆空间指针类型
p := &Person{...}堆空间指针类型
var p Person通常栈空间值类型❌(栈自动释放)
工厂函数返回指针堆空间指针类型

💡 注:Go 编译器通过逃逸分析决定实际内存位置,大对象通常分配在堆上

2. 初始化方式对比

​创建方式​​初始化控制​​默认值处理​​典型代码示例​
p := Person{...}✅ 显式指定字段值未指定字段=零值Person{Name: "Alice"}
p := new(Person)❌ 必须先创建后赋值所有字段=零值p := new(Person); p.Name="Bob"
p := &Person{...}✅ 显式指定字段值未指定字段=零值&Person{Name: "Charlie"}
var p Person❌ 零值初始化所有字段=零值var p Person
工厂函数✅ 完全控制可自定义缺省值NewPerson("David", 35)

3. 修改行为与内存开销

值类型实例 (Person{}或var p Person)

func modify(p Person) {
    p.Name = "Modified" // 修改副本
}
 
func main() {
    p := Person{Name: "Original"}
    modify(p)
    fmt.Println(p.Name) // 输出 "Original" (未修改)
}
  • ✅ 优点:无GC压力,内存连续
  • ❌ 缺点:传递时产生完整拷贝​(大结构体性能差)

指针类型实例 (new()或&Person{})

func modify(p *Person) {
    p.Name = "Modified" // 修改原对象
}
 
func main() {
    p := &Person{Name: "Original"}
    modify(p)
    fmt.Println(p.Name) // 输出 "Modified"
}
  • ✅ 优点:传递高效(仅拷贝指针)
  • ❌ 缺点:增加GC压力,多一次指针解引用

4. 实际内存布局示意图

值类型实例

栈内存
┌───────────────────┐
│ Person实例        │
│ Name: "Alice"     │
│ Age: 30           │
└───────────────────┘

指针类型实例

栈内存         堆内存
┌───────┐      ┌───────────────────┐
│ 指针  │─────>│ Person实例        │
└───────┘      │ Name: "Bob"       │
               │ Age: 25           │
               └───────────────────┘

5. 各场景使用建议

​场景​​推荐方式​​原因​
小型结构体 (<64字节)Person{...}避免堆分配开销
大型结构体或需要跨函数修改&Person{...}减少拷贝成本
需要自定义初始化逻辑工厂函数封装复杂逻辑/参数校验
数据库映射对象&Struct{...}ORM通常需要可修改的指针对象
高频创建的临时小对象var p Struct栈分配快速
接口实现对象工厂函数返回接口return &implStruct{}, implements SomeInterface

性能测试对比

type BigStruct [1024]int64  // 8KB大对象
 
// 测试值传递
func BenchmarkValue(b *testing.B) {
    var s BigStruct
    for i := 0; i < b.N; i++ {
        processValue(s)
    }
}
 
// 测试指针传递
func BenchmarkPointer(b *testing.B) {
    s := new(BigStruct)
    for i := 0; i < b.N; i++ {
        processPointer(s)
    }
}

结果:

  • 值传递​:每次调用拷贝 8KB 数据
  • 指针传递​:每次调用仅拷贝 8 字节指针
  • 大对象场景指针效率高 1000 倍+

终极选择指南

​默认首选​:obj := &SomeStruct{...}

  • 适应大多数场景
  • 清晰表达对象可变性
  • 高效传递

特殊场景选择​:

// 不可变配置对象
config := AppConfig{Port: 8080}
 
// 零值有特殊含义
var zeroTime time.Time
 
// 微优化关键路径
var localVar SmallStruct

大型项目​:​工厂函数统一创建

// user.go
func NewUser(name string, age int) *User {
    return &User{
        Name: name,
        Age: age,
        regTime: time.Now(),
    }
}

遵循这些原则可在安全性和性能间取得最佳平衡💡

到此这篇关于Go语言创建结构体实例对象的几种常用方式的文章就介绍到这了,更多相关Go语言创建结构体实例对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go语言操作Excel利器之excelize类库详解

    Go语言操作Excel利器之excelize类库详解

    Excelize是Go语言编写的用于操作Office Excel文档基础库,基于ECMA-376,ISO/IEC 29500国际标准,可以使用它来读取、写入由Excel 2007及以上版本创建的电子表格文档,下面这篇文章主要给大家介绍了关于Go语言操作Excel利器之excelize类库的相关资料,需要的朋友可以参考下
    2022-10-10
  • Go语言导出内容到Excel的方法

    Go语言导出内容到Excel的方法

    这篇文章主要介绍了Go语言导出内容到Excel的方法,涉及Go语言操作excel的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • golang频率限制 rate详解

    golang频率限制 rate详解

    这篇文章主要介绍了golang频率限制 rate详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • gin 获取post请求的json body操作

    gin 获取post请求的json body操作

    这篇文章主要介绍了gin 获取post请求的json body操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • 在go中使用omitempty的代码实例

    在go中使用omitempty的代码实例

    今天小编就为大家分享一篇关于在go中使用omitempty的代码实例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • Go语言题解LeetCode705设计哈希集合

    Go语言题解LeetCode705设计哈希集合

    这篇文章主要为大家介绍了Go语言题解LeetCode705设计哈希集合,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 一文详细介绍golang中.()类型断言的使用方法

    一文详细介绍golang中.()类型断言的使用方法

    Golang是一门非常流行的编程语言,在很多领域都有着广泛的应用,在开发过程中,很多时候我们需要将函数作为参数传递给其他函数,这时候就需要用到golang中的.()用法,本文将详细介绍golang中.()的使用方法,需要的朋友可以参考下
    2023-08-08
  • Go语言 go程释放操作(退出/销毁)

    Go语言 go程释放操作(退出/销毁)

    这篇文章主要介绍了Go语言 go程释放操作(退出/销毁),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • Go语言使用WaitGroup等待多个协程完成

    Go语言使用WaitGroup等待多个协程完成

    sync.WaitGroup是Go标准库中的一个结构体,用于等待一组goroutine执行完成,本文就来介绍一下Go语言使用WaitGroup等待多个协程完成,感兴趣的可以了解一下
    2026-02-02
  • go开源项目用户名密码验证的逻辑鬼才写法

    go开源项目用户名密码验证的逻辑鬼才写法

    这篇文章主要为大家介绍了go开源项目中发现的一个逻辑鬼才写法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07

最新评论