本文深入探讨了go语言中因未初始化map或其内部结构体指针而导致的`invalid memory address or nil pointer dereference`运行时错误。通过分析一个在并发环境中向嵌套切片追加数据的常见场景,文章详细解释了如何正确初始化map、处理map中不存在的键,并安全地初始化嵌套的结构体和切片,从而避免运行时恐慌,确保程序的健壮性。
在Go语言中,panic: runtime error: invalid memory address or nil pointer dereference 是一个常见的运行时错误,通常意味着程序尝试访问一个未初始化的指针(即nil指针)所指向的内存地址。当涉及到复杂的嵌套数据结构,特别是包含map和结构体指针时,这类问题更容易出现。
考虑以下代码示例,它尝试在一个并发的goroutine中向一个嵌套在map中的结构体切片追加数据:
package main
import (
"fmt"
"sync"
"time"
)
var PairNames = []string{ "kalle", "kustaa", "daavid", "pekka" }
type Data struct {
a int
b int
}
type Tickers struct {
Tickers []Data
}
type Pairs struct {
Pair map[string]*Tickers
Mutex sync.Mutex
}
func (pairs Pairs) CollectTickers() {
PairCount := len(PairNames)
for x := 0; x <= 1000; x++ {
for i := 0; i < PairCount-1; i++ {
var data Data
data.a = i * x
data.b = i + x
pairs.Mutex.Lock()
// 错误发生在这里
pairs.Pair[PairNames[i]].Tickers = append(pairs.Pair[PairNames[i]].Tickers, data)
pairs.Mutex.Unlock()
fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
}
}
}
func main() {
var pairs Pairs // pairs.Pair 此时为 nil
go pairs.CollectTickers()
time.Sleep(100 * time.Second)
}运行上述代码会导致 panic: runtime error: invalid memory address or nil pointer dereference 错误,错误发生在 pairs.Pair[PairNames[i]].Tickers = append(...) 这一行。
这个错误主要由以下两个原因造成:
简而言之,问题在于在尝试访问 Tickers 字段之前,pairs.Pair 或 pairs.Pair[PairNames[i]] 中的至少一个为 nil。
要解决这个问题,我们需要确保在使用map和其内部的指针字段之前,它们都已经被正确地初始化。
在 main 函数中,必须先使用 make 函数初始化 Pairs 结构体中的 Pair map:
func main() {
var pairs = Pairs{
Pair: make(map[string]*Tickers), // 初始化map
}
go pairs.CollectTickers()
time.Sleep(1 * time.Second)
}在 CollectTickers 方法中,当从 pairs.Pair 中获取 *Tickers 类型的实例时,需要检查该键是否存在。如果不存在,则需要创建一个新的 Tickers 实例并将其添加到map中。
Go语言提供了一种惯用的方式来检查map中是否存在某个键,即“逗号-ok”语法:value, ok := myMap[key]。
func (pairs Pairs) CollectTickers() {
PairCount := len(PairNames)
for x := 0; x <= 1000; x++ {
for i := 0; i < PairCount-1; i++ {
var data Data
data.a = i * x
data.b = i + x
pairs.Mutex.Lock()
name := PairNames[i]
if t, ok := pairs.Pair[name]; ok {
// 键已存在,直接追加数据到其Tickers切片
t.Tickers = append(t.Tickers, data)
} else {
// 键不存在,创建新的Tickers实例并初始化其Tickers切片
pairs.Pair[name] = &Tickers{
Tickers: []Data{data}, // 初始化时直接包含第一个数据
}
}
pairs.Mutex.Unlock()
fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
}
}
}将上述两步修正合并到一起,得到一个可以正确运行且避免nil指针恐慌的代码:
package main
import (
"fmt"
"sync"
"time"
)
var PairNames = []string{"kalle", "kustaa", "daavid", "pekka"}
type Data struct {
a int
b int
}
type Tickers struct {
Tickers []Data
}
type Pairs struct {
Pair map[string]*Tickers
Mutex sync.Mutex
}
func (pairs Pairs) CollectTickers() {
PairCount := len(PairNames)
for x := 0; x <= 1000; x++ {
for i := 0; i < PairCount-1; i++ {
var data Data
data.a = i * x
data.b = i + x
pairs.Mutex.Lock() // 在访问map前加锁
name := PairNames[i]
if t, ok := pairs.Pair[name]; ok {
// 如果键已存在,直接向其Tickers切片追加数据
t.Tickers = append(t.Tickers, data)
} else {
// 如果键不存在,则创建新的Tickers实例并初始化其Tickers切片
pairs.Pair[name] = &Tickers{
Tickers: []Data{data}, // 初始化时包含第一个数据
}
}
pairs.Mutex.Unlock() // 访问map后解锁
fmt.Printf("a = %v, b = %v\r\n", data.a, data.b)
}
}
}
func main() {
// 初始化Pairs结构体,特别是其内部的map字段
var pairs = Pairs{
Pair: make(map[string]*Tickers),
}
go pairs.CollectTickers()
// 为了确保goroutine有足够时间运行,将sleep时间调整为1秒
time.Sleep(1 * time.Second)
}invalid memory address or nil pointer dereference 错误在Go语言中通常是由于未初始化或不当使用指针导致的。在处理包含map和嵌套结构体(特别是当这些结构体字段也是指针或切片时)的复杂数据结构时,务必牢记以下几点:
通过遵循这些最佳实践,可以显著提高Go语言程序的健壮性和可靠性,有效避免常见的运行时恐慌。
# go
# go语言
# app
# ai
# 并发访问
# 键值对
# String
# Error
# 结构体
# 指针
# 数据结构
# 指针类型
相关文章:
如何选择美橙互联多站合一建站方案?
网站制作公司广州有几家,广州尚艺美发学校网站是多少?
官网建站费用明细查询_企业建站套餐价格及收费标准指南
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
高防服务器租用首荐平台,企业级优惠套餐快速部署
Bpmn 2.0的XML文件怎么画流程图
制作旅游网站html,怎样注册旅游网站?
上海网站制作网页,上海本地的生活网站有哪些?最好包括生活的各个方面的?
建站之星如何保障用户数据免受黑客入侵?
香港服务器部署网站为何提示未备案?
标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?
高端建站三要素:定制模板、企业官网与响应式设计优化
重庆市网站制作公司,重庆招聘网站哪个好?
专业制作网站的公司哪家好,建立一个公司网站的费用.有哪些部分,分别要多少钱?
如何在IIS服务器上快速部署高效网站?
IOS倒计时设置UIButton标题title的抖动问题
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
广州网站建站公司选择指南:建站流程与SEO优化关键词解析
如何在腾讯云免费申请建站?
c++怎么使用类型萃取type_traits_c++ 模板元编程类型判断【方法】
Avalonia如何实现跨窗口通信 Avalonia窗口间数据传递
,南京靠谱的征婚网站?
广州网站设计制作一条龙,广州巨网网络科技有限公司是干什么的?
小型网站建站如何选择虚拟主机?
网站制作和推广的区别,想自己建立一个网站做推广,有什么快捷方法马上做好一个网站?
网站海报制作教学视频教程,有什么免费的高清可商用图片网站,用于海报设计?
ui设计制作网站有哪些,手机UI设计网址吗?
如何在Windows虚拟主机上快速搭建网站?
哈尔滨网站建设策划,哈尔滨电工证查询网站?
建站之星后台密码遗忘?如何快速找回?
香港服务器租用费用高吗?如何避免常见误区?
如何自定义建站之星模板颜色并下载新样式?
专业网站制作服务公司,有哪些网站可以免费发布招聘信息?
如何零基础在云服务器搭建WordPress站点?
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
如何在搬瓦工VPS快速搭建网站?
陕西网站制作公司有哪些,陕西凌云电器有限公司官网?
网站制作网站,深圳做网站哪家比较好?
建站主机选择指南:服务器配置与SEO优化实战技巧
建站之星多图banner生成与模板自定义指南
建站之星如何实现五合一智能建站与营销推广?
建站之星后台密码如何安全设置与找回?
可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?
如何构建满足综合性能需求的优质建站方案?
如何在云主机上快速搭建网站?
如何通过FTP空间快速搭建安全高效网站?
,如何利用word制作宣传手册?
宠物网站制作html代码,有没有专门介绍宠物如何养的网站啊?
广德云建站网站建设方案与建站流程优化指南
Android自定义控件实现温度旋转按钮效果
*请认真填写需求信息,我们会在24小时内与您取得联系。