当前位置:首页 > 文章列表 > Golang > Go教程 > Go new 表达式怎样直接初始化带默认值指针

Go new 表达式怎样直接初始化带默认值指针

来源:17golang原创 2026-10-26 17:37:24 0浏览 收藏

Go 1.26 起,可以直接用 new(3)、new(false) 或 new(计算表达式) 创建带初始值的指针。例如字段类型为 *int 时,写 Retries: new(3) 即可。这里的“默认值”由调用方明确提供,不会自动读取结构体标签或某个默认配置。

旧写法 new(int) 继续有效,但它创建的是值为 0 的 int 变量。要把初始值设成 3,应传表达式 3;如果需要 *int64,就显式写 new(int64(3))。下面用任务重试配置说明实际写法。

Go 官方地址:https://go.dev/

先确认工具链和模块语言版本

表达式作为 new 参数是 Go 1.26 加入的语言能力。除了工具链支持,也要确认模块启用的语言版本;不能因为机器装了新工具链,就假定旧模块自动接受全部新语法。新建独立示例时可以这样准备:

# 在独立目录建立示例,并显式启用所需语言版本
mkdir new-default-demo
cd new-default-demo
go mod init example.com/new-default-demo
go mod edit -go=1.26.0
# 查看实际工具链,后续命令供读者自行执行
go version

不要为试一行语法直接提高业务仓库的最低 Go 版本。团队工具链与 CI 都满足要求时再修改模块配置。本文代码和后文结果均供读者复现,没有把推导出的值当作本机实测记录。

给可选配置字段设置明确初始值

把以下内容保存为 main.go。Retries 和 Enabled 都使用指针,借此区分“未指定”与“指定了一个值”。fallback 是本例业务代码定义的回退值,不是 new 提供的特殊机制。

package main

import "fmt"

type TaskOptions struct {
    Retries *int
    Enabled *bool
}

func retriesOrDefault(value *int, fallback int) int {
    // 必须先判断 nil;显式的 0 不能被误当成未指定。
    if value == nil {
        return fallback
    }
    return *value
}

func main() {
    preset := TaskOptions{
        Retries: new(3),
        Enabled: new(false),
    }
    explicitZero := TaskOptions{Retries: new(0)}
    unspecified := TaskOptions{}

    // new(false) 返回非 nil 指针,解引用后才是 false。
    fmt.Printf("preset=%d enabled=%t\n",
        retriesOrDefault(preset.Retries, 5), *preset.Enabled)
    fmt.Printf("zero=%d missing=%d\n",
        retriesOrDefault(explicitZero.Retries, 5),
        retriesOrDefault(unspecified.Retries, 5))
}

按程序逻辑,preset 的重试值为 3,enabled 为 false;显式零次重试仍为 0,未指定重试次数才使用 fallback 5。若只是普通 int 字段而不需要区分未指定,直接存 int 往往更简单,不必为使用新语法而增加指针。

可选重试配置中nil零值和显式初始值的关系
图1:可选配置结构图。非 nil 指针保存显式值,nil 表示没有指定;回退策略属于业务函数。图中为静态说明,未展示运行证据。
# 在启用 Go 1.26 语言版本的示例模块内运行
go run .

读者可以检查两行打印值是否符合上面的预期,再把 new(3) 改成 new(1 + 2) 观察同样的值。表达式也可以是返回单个值的函数调用;若调用带有副作用,它仍会正常求值,不要把 new 当成延迟执行器。

区分 new(变量) 与对原变量取地址

new(x) 会创建一个新变量,以 x 当前的值初始化。它不把指针直接指向 x。因此修改返回指针指向的 int,不会修改原来的 int。下面片段可放在 main 函数中:

// copied 指向独立变量,alias 指向 original 本身。
original := 7
copied := new(original)
alias := &original

*copied = 9
fmt.Println(original, *copied) // 预期为 7 和 9。

*alias = 11
fmt.Println(original, *alias) // 预期为 11 和 11。

如果本意是让其他代码修改 original,就应使用 &original。若要创建一个独立的默认标量值,则 new(original) 表达得更直接。这种独立是变量层面的,不是所有对象的深拷贝:表达式是切片或 map 时,其值中引用的底层数据仍可能共享;不能由“新变量”推导出“完整复制所有数据”。

new变量副本与原变量地址的区别
图2:指针归属结构图。copied 关联新变量,alias 关联 original;两种指针写法表达不同的修改目标,连线不表示执行流程。

显式控制类型,并分清 nil 与零值

写法得到的指针及初始值使用提醒
new(int)*int,值为 0参数是类型
new(3)*int,值为 3无类型整数常量采用默认类型
new(int64(3))*int64,值为 3目标字段为 *int64 时显式转换
new(false)*bool,值为 false指针本身不是 nil
new(nil)不合法预声明 nil 不能直接作参数

字段上下文不能把 new(3) 的结果自动变成 *int64。先让表达式具有所需类型,再创建指针。命名类型也可以采用相同思路:

type RetryCount int

// 通过转换明确表达式类型,保留业务命名类型。
count := new(RetryCount(3))
fmt.Printf("%T %d\n", count, *count)

若需要的是一个未指定的 *int,直接声明 var value *int 即可,不要写 new(nil)。若确实要创建“指向一个 nil 指针变量的指针”,那是 **int 这一类不同需求,应先明确类型,避免在默认配置代码中混淆层级。

旧项目怎样保留同样的行为

项目暂时不启用 Go 1.26 时,仍可用局部变量取地址。下面函数与创建一个初始值为 3 的独立 int 指针表达相同目的,不需要手动释放局部变量:

// 传统写法适用于不采用 new 表达式语法的项目。
func defaultRetries() *int {
    value := 3
    return &value
}

对于已经有通用指针辅助函数的代码库,应把最低语言版本、现有风格和可读性一起考虑,没必要仅为了缩短几个字符而全量迁移。new 也不承诺对象一定在堆上;不要把语法变化当成减少分配或提高性能的证据。

结构体字段没有赋值时会自动得到 new(默认值) 吗?

不会。未赋值的指针字段仍是 nil。需要默认指针时,在构造函数或结构体字面量中明确赋值。

new(false) 与 nil 有什么区别?

new(false) 表示已经指定 false;nil 可以由业务解释成未指定。应先判断指针,再读取指向的值。

为什么升级 Go 后仍然报语法不支持?

除了实际工具链,也要检查 go.mod 语言版本和编辑器使用的工具链配置。对本例,先确认示例模块显式使用 Go 1.26 或更高语言版本。

语言能力引入见 Go 1.26 发布说明;类型、初始值与 nil 规则见 Go 语言规范 Allocation。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go 泛型自引用约束怎样表达递归接口Go 泛型自引用约束怎样表达递归接口
上一篇
Go 泛型自引用约束怎样表达递归接口
Go netip.Prefix.Contains 怎样判断 IP 是否属于指定网段
下一篇
Go netip.Prefix.Contains 怎样判断 IP 是否属于指定网段
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    713次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    716次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    798次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    758次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    589次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码