0

0

Go语言中 new 的使用场景详解

DDD

DDD

发布时间:2025-07-16 17:08:13

|

723人浏览过

|

来源于php中文网

原创

go语言中 new 的使用场景详解

本文旨在深入解析 Go 语言中 new 关键字的使用场景。我们将探讨 new 与 make 的区别,new(MyStruct) 与 &MyStruct{} 的异同,以及如何利用 new 结合工厂函数进行对象初始化,从而编写更健壮、更易维护的 Go 代码。

在 Go 语言中,new 是一个内置函数,用于分配内存。理解 new 的使用场景对于编写高效、可维护的 Go 代码至关重要。本文将深入探讨 new 的作用,以及它与其他内存分配方式(如 make 和 &) 的区别。

new 的基本作用

new(T) 会分配一个类型为 T 的零值,并返回指向该零值的指针。 重要的是,new 返回的是一个指针,指向新分配的内存空间。

例如:

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

package main

import "fmt"

func main() {
    i := new(int)
    fmt.Printf("Type: %T, Value: %v, Address: %p\n", i, *i, i) // Type: *int, Value: 0, Address: 0x...
}

在这个例子中,new(int) 分配了一个 int 类型的零值 (0) 并返回指向该零值的指针。

new 与 make 的区别

new 和 make 都是 Go 语言中用于分配内存的内置函数,但它们的应用场景不同:

  • new: 用于分配零值内存,返回指向该内存的指针。适用于 int、float、struct 等类型。
  • make: 用于分配并初始化引用类型(slice、map、channel),返回的是引用类型本身,而不是指针。

以下代码展示了 make 的使用:

package main

import "fmt"

func main() {
    s := make([]float64, 10) // 创建一个长度为10的 float64 切片
    fmt.Printf("Type: %T, Value: %v, Len: %d, Cap: %d\n", s, s, len(s), cap(s)) // Type: []float64, Value: [0 0 0 0 0 0 0 0 0 0], Len: 10, Cap: 10

    m := make(map[string]int) // 创建一个 string 到 int 的 map
    m["key"] = 1
    fmt.Printf("Type: %T, Value: %v\n", m, m) // Type: map[string]int, Value: map[key:1]

    ch := make(chan int) // 创建一个 int 类型的 channel
    go func() { ch <- 1 }()
    val := <-ch
    fmt.Printf("Type: %T, Value: %v\n", ch, val) // Type: chan int, Value: 1
    close(ch)
}

尝试用 new 分配 slice 或 map 会导致意想不到的结果,如下所示:

《PHP设计模式指南》中文版
《PHP设计模式指南》中文版

《PHP设计模式》首先介绍了设计模式,讲述了设计模式的使用及重要性,并且详细说明了应用设计模式的场合。接下来,本书通过代码示例介绍了许多设计模式。最后,本书通过全面深入的案例分析说明了如何使用设计模式来计划新的应用程序,如何采用PHP语言编写这些模式,以及如何使用书中介绍的设计模式修正和重构已有的代码块。作者采用专业的、便于使用的格式来介绍相关的概念,自学成才的编程人员与经过更多正规培训的编程人员

下载
package main

import "fmt"

func main() {
    y := new([]float64)
    fmt.Printf("Type: %T, Len = %d\n", y, len(*y)) // Type: *[]float64, Len = 0
    // *y[0] = 1  // panic: index out of range [0] with length 0
}

new([]float64) 分配了一个指向 nil 切片的指针。 切片本身并没有分配内存,因此长度为 0,无法直接使用。

总结:

函数 作用 返回值 适用类型
new 分配零值内存,返回指向该内存的指针 指针 int、float、struct 等
make 分配并初始化引用类型,返回引用类型本身 引用类型 slice、map、channel

new(MyStruct) vs &MyStruct{}

对于结构体,new(MyStruct) 和 &MyStruct{} 都能够分配内存并返回指向结构体的指针。 它们之间的区别在于:

  • new(MyStruct): 分配一个 MyStruct 类型的零值,并返回指向该零值的指针。
  • &MyStruct{}: 分配一个 MyStruct 类型的零值,并返回指向该零值的指针,但可以使用字面量初始化结构体成员。
package main

import "fmt"

type MyStruct struct {
    Name string
    Age  int
}

func main() {
    // 使用 new
    s1 := new(MyStruct)
    s1.Name = "Alice"
    s1.Age = 30
    fmt.Printf("s1: %+v\n", s1) // s1: &{Name:Alice Age:30}

    // 使用 &{}
    s2 := &MyStruct{Name: "Bob", Age: 25}
    fmt.Printf("s2: %+v\n", s2) // s2: &{Name:Bob Age:25}
}

从功能上讲,两者几乎没有区别。 选择哪种方式通常取决于代码的可读性和个人偏好。 如果需要初始化结构体的某些字段,使用 &MyStruct{} 会更加方便。

使用 new 和工厂函数进行对象初始化

Go 语言没有内置的构造函数。 通常,我们会使用工厂函数结合 new 来进行对象的初始化。 这种方式可以隐藏结构体的内部实现细节,并提供更灵活的初始化逻辑。

package main

import "fmt"

type MyStruct struct {
    name    string // 私有字段
    age     int    // 私有字段
    isAdult bool   // 私有字段
}

// 工厂函数
func NewMyStruct(name string, age int) *MyStruct {
    if age < 18 {
        return nil // 或者返回一个默认值
    }

    s := new(MyStruct)
    s.name = name
    s.age = age
    s.isAdult = true
    return s
}

func (s *MyStruct) GetName() string {
    return s.name
}

func main() {
    s := NewMyStruct("Charlie", 20)
    if s != nil {
        fmt.Printf("Name: %s, Age: %d, IsAdult: %t\n", s.GetName(), s.age, s.isAdult) // Name: Charlie, Age: 20, IsAdult: true
    }

    s2 := NewMyStruct("David", 16)
    if s2 == nil {
        fmt.Println("Invalid age") // Invalid age
    }
}

在这个例子中,NewMyStruct 是一个工厂函数,它负责创建并初始化 MyStruct 对象。 通过工厂函数,我们可以控制对象的创建过程,并隐藏内部字段。

使用工厂函数的优点:

  • 封装性: 隐藏结构体的内部实现细节,只暴露必要的接口。
  • 初始化逻辑: 可以在工厂函数中执行复杂的初始化逻辑,例如验证参数、设置默认值等。
  • 控制对象创建: 可以限制对象的创建,例如实现单例模式。
  • 易于维护: 当结构体的内部结构发生变化时,只需要修改工厂函数,而不需要修改所有使用该结构体的代码。

总结

new 是 Go 语言中一个重要的内置函数,用于分配内存。 理解 new 的使用场景,以及它与 make 和 & 的区别,对于编写高质量的 Go 代码至关重要。 结合工厂函数使用 new 可以提供更灵活、更健壮的对象初始化方式,从而提高代码的可维护性和可扩展性。

相关专题

更多
css中float用法
css中float用法

css中float属性允许元素脱离文档流并沿其父元素边缘排列,用于创建并排列、对齐文本图像、浮动菜单边栏和重叠元素。想了解更多float的相关内容,可以阅读本专题下面的文章。

553

2024.04.28

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

95

2025.10.23

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

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

193

2025.06.09

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

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

186

2025.07.04

string转int
string转int

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

312

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

522

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

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

49

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

190

2025.08.29

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

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

精品课程

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

共28课时 | 4万人学习

Kotlin 教程
Kotlin 教程

共23课时 | 2.2万人学习

Go 教程
Go 教程

共32课时 | 3.2万人学习

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

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