当前位置: 首页 > news >正文

Go 语言make函数

在 Go 语言中,make 函数是用于初始化引用类型(切片 slice、映射 map 和通道 channel)的内置函数。以下是需要用到 make 函数的典型场景:

1. 创建切片(Slice)

当需要指定长度和容量时,必须用 make

// 创建长度为 3,容量为 5 的 int 切片
s := make([]int, 3, 5)
  • 直接声明 var s []int 得到的是 nil 切片
  • make 会分配底层数组内存并初始化零值

2. 创建映射(Map)

所有 map 必须用 make 初始化才能使用

// 正确:初始化空 map
m := make(map[string]int)// 错误:未初始化的 nil map 会 panic!
var nilMap map[string]int
nilMap["key"] = 42 // panic: assignment to nil map
  • 可选指定初始容量(提升性能):
  m := make(map[int]string, 100) // 预分配 100 个键值对的空间

意义相同写法不同:

// 使用字面量初始化(直接包含初始键值对)
m := map[string]int{"Alice": 30,"Bob":   25,
}// 等价于使用 make + 赋值
m := make(map[string]int)
m["Alice"] = 30
m["Bob"] = 25

关键区别在于:

  1. 隐式内存分配:字面量语法会自动调用 make 进行内存分配
  2. 初始化即赋值:适合在声明时已知具体键值对的情况
  3. 代码简洁性:省去了显式的 make 调用和后续的多次赋值操作

只有当需要创建空映射(没有初始元素)或需要指定初始容量时,才需要显式使用 make

// 需要显式 make 的情况
emptyMap := make(map[string]int)       // 空映射
preAllocatedMap := make(map[string]int, 10) // 预分配容量

3. 创建通道(Channel)

初始化通道时必须用 make

// 无缓冲通道
ch1 := make(chan int)// 带缓冲通道(容量为 10)
ch2 := make(chan string, 10)

4. 需要预分配空间时

使用 make 预分配内存可避免频繁扩容,提升性能:

// 预分配 1w 个元素的切片(避免 append 时多次扩容)
data := make([]int, 0, 10_000)// 预分配大容量 map
cache := make(map[int]float64, 5000)

关键区别:make vs new

特性makenew
适用类型slice, map, channel任意类型(如 struct, int 等)
返回值初始化后的引用类型指向类型的指针 (*T)
内存初始化分配内存并初始化(如 slice 的零值填充)分配零值内存,返回指针
示例m := make(map[int]bool)p := new(int) → *p = 10

何时用 make?总结

  1. 创建非零值的 slice/map/channel
  2. 需要预分配内存容量时
  3. 避免 nil 引用导致 panic 时
   // 安全用法m := make(map[string]int)m["safe"] = 1 // 正常

典型示例场景

func main() {// 场景1:需要初始化后才能操作的 mapconfig := make(map[string]string)config["env"] = "production"// 场景2:预分配大切片data := make([]int, 0, 1e6) // 100万容量for i := 0; i < 1e6; i++ {data = append(data, i) // 避免多次扩容}// 场景3:创建通道ch := make(chan os.Signal, 1)signal.Notify(ch, syscall.SIGINT)
}

📌 经验法则: 当处理 slice/map/channel 时,优先考虑 make——除非你确定需要 nil 语义(如返回 nil 表示异常)。

扩展:Map函数的用法 

完整示例

package mainimport ("fmt""sync"
)func main() {// 初始化包含两个元素的 mapm := map[string]int{"Alice": 30,"Bob":   25,}// 添加新元素(当前 map 包含 3 个元素)m["Eve"] = 28// 更新现有元素(Alice 的年龄更新为 31)m["Alice"] = 31// 安全检查 Dave 是否存在(使用 exists 布尔值判断)if age, exists := m["Dave"]; exists {fmt.Println("Dave exists:", age)} else {fmt.Println("Dave not found") // 会执行这里}// 获取当前 map 长度(此时为 3,因为已添加 Eve)fmt.Println("Map length:", len(m))// 预分配容量的 map 初始化(容量 10,但可自动扩展)preAllocatedMap := make(map[string]int, 10)preAllocatedMap["test"] = 100fmt.Println("Pre-allocated map:", preAllocatedMap)// 删除 Eve 元素(map 长度变为 2)delete(m, "Eve")// 遍历当前 map(顺序随机)for name, age := range m {fmt.Printf("%s: %d\n", name, age) // 输出 Alice:31 和 Bob:25}// 并发安全控制结构var (safeMap = make(map[int]string) // 需要互斥锁保护的 mapmu      sync.Mutex             // 互斥锁)// 启动 goroutine 安全写入go func() {mu.Lock()safeMap[1] = "Hello" // 加锁后写入mu.Unlock()}()// 清空 map 所有元素clear(m)fmt.Println(m) // 输出空 map:map[]
}

输出:

Dave not found
Map length: 3
Pre-allocated map: map[test:100]
Alice: 31
Bob: 25
map[]

http://www.dtcms.com/a/306858.html

相关文章:

  • 输电线路绝缘子泄漏电流在线监测装置的技术解析与应用价值
  • Python读取获取波形图波谷/波峰
  • Directory Opus 使用优化
  • 30道JS高频经典笔试题集合+详解(一)
  • 视觉系统引导冲床冲压:工业自动化的“智能之眼”
  • Dify 从入门到精通(第 4/100 篇):快速上手 Dify 云端:5 分钟创建第一个应用
  • AI培训项目《人工智能大模型应用工程师》课程学习大纲分享!
  • 【sklearn(01)】数据集加载、划分,csv文件创建,特征工程,无量纲化
  • 【编号65】广西地理基础数据(道路、水系、四级行政边界、地级城市、DEM等)
  • 我的世界模组开发教程——资源(1)
  • JeecgBoot(1):前后台环境搭建
  • C#_创建自己的MyList列表
  • 汽车电子控制系统开发的整体安全理念
  • SOA增益谱与ASE光谱的区别
  • SSRF漏洞基础
  • RESTful API和WebSocket的优缺点,各自适合以及不适合什么样的场景
  • LLM 模型部署难题的技术突破:从轻量化到分布式推理的全栈解决方案
  • uni-app webview的message监听不生效(uni.postmessage is not a function)
  • 嵌入式第十五课!!!!指针函数(续)+函数指针+二级指针+指针数组!!!
  • Java 14 新特性解析与代码示例
  • OWSM v4 语音识别学习笔记
  • RK3506-G2 开箱使用体验
  • 【Python】 切割图集的小脚本
  • 【WRF-Chem第五期】自定义字段配置 iofields_filename 详述
  • 红绿多空策略
  • 全包圆230㎡整装案例亮相,空间美学演绎东方韵味
  • Netty是如何解决epoll CPU占用100%问题的
  • 借助 Wisdom SSH AI 助手构建 Linux 容器化开发流水线
  • 构建智能体(Agent)时如何有效管理其上下文
  • 2022 年 NOI 最后一题题解