Go new 表达式怎样直接初始化带默认值指针
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 往往更简单,不必为使用新语法而增加指针。

# 在启用 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 时,其值中引用的底层数据仍可能共享;不能由“新变量”推导出“完整复制所有数据”。

显式控制类型,并分清 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。
Go 泛型自引用约束怎样表达递归接口
- 上一篇
- Go 泛型自引用约束怎样表达递归接口
- 下一篇
- Go netip.Prefix.Contains 怎样判断 IP 是否属于指定网段
-
- Golang · Go教程 | 53分钟前 |
- Go 泛型自引用约束怎样表达递归接口
- 219浏览 收藏
-
- Golang · Go教程 | 55分钟前 |
- Go //go:fix inline 怎样为 API 迁移准备内联规则
- 417浏览 收藏
-
- Golang · Go教程 | 55分钟前 | go · 工具链 · 兼容性 · Go 工具链迁移 go:linkname 链接器
- Go linkname 的使用边界怎样判断是否应迁移
- 420浏览 收藏
-
- Golang · Go教程 | 57分钟前 |
- Go go mod edit 怎样批量修改模块路径
- 262浏览 收藏
-
- Golang · Go教程 | 1小时前 | Go go.work go work use 多模块工作区
- Go go work use 怎样把多个模块加入工作区
- 288浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go go env -changed 怎样找出修改过的环境配置
- 191浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go go list -m -json 怎样导出模块构建信息
- 451浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go go tool pprof 怎样切换采样指标查看内存
- 403浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go testing/iotest.TimeoutReader 怎样测试读超时
- 292浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Go testing.B.Loop 怎样防止无副作用调用被编译器优化
- 266浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 713次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 716次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 798次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 758次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 589次使用
-
- Java 性能优化上线清单:从定位、改造到灰度发布
- 2026-06-11 860浏览
-
- Spring Boot 压测验证:Gatling、JMeter 与性能回归门禁
- 2026-06-11 843浏览
-
- Java NMT 非堆内存排查:Direct Buffer、线程栈与 Metaspace 分析
- 2026-06-11 826浏览
-
- Spring Boot 容器内存优化:JVM 堆、非堆与 MaxRAMPercentage
- 2026-06-11 809浏览
-
- Tomcat 连接与线程参数调优:maxThreads、acceptCount 与 KeepAlive
- 2026-06-11 792浏览

