Golang运行时错误:无效内存地址或空指针解引用 [SIGSEGV信号:段错误 code=0x1 addr=0x30 pc=0x7d65b6]

Golang运行时错误:无效内存地址或空指针解引用 [SIGSEGV信号:段错误 code=0x1 addr=0x30 pc=0x7d65b6] errorlog.txt

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0x7d65b6]

goroutine 9 [running]:
github.com/gomodule/redigo/redis.(*Pool).waitVacantConn(0x7f67fc9e3c00?, {0x973598?, 0xc000024040?})
	/build/sources/go/pkg/mod/github.com/gomodule/redigo@v1.8.9/redis/pool.go:357 +0x36
github.com/gomodule/redigo/redis.(*Pool).GetContext(0x0, {0x973598, 0xc000024040})
	/build/sources/go/pkg/mod/github.com/gomodule/redigo@v1.8.9/redis/pool.go:200 +0x45
github.com/gomodule/redigo/redis.(*Pool).Get(...)
	/build/sources/go/pkg/mod/github.com/gomodule/redigo@v1.8.9/redis/pool.go:186

此文件已被截断。显示原文

main.go

package main

import (
	"fmt"
	"gitlab.com/harish/calls/redis"
)



func main() {

此文件已被截断。显示原文

redis.go

package redis

import (
	"fmt"
	"log"
	"time"

	"github.com/gomodule/redigo/redis"
)

此文件已被截断。显示原文


更多关于Golang运行时错误:无效内存地址或空指针解引用 [SIGSEGV信号:段错误 code=0x1 addr=0x30 pc=0x7d65b6]的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你的 main.go 文件是不是应该写成 RedisConn = redis.Setup()?我没看到 RedisConn 是在哪里被设置的。

更多关于Golang运行时错误:无效内存地址或空指针解引用 [SIGSEGV信号:段错误 code=0x1 addr=0x30 pc=0x7d65b6]的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这个错误是由于在 redis.go 文件中,RedisPool 变量在使用前没有被正确初始化导致的。从堆栈跟踪可以看出,在 pool.go:200 行调用 GetContext 方法时,接收器(pool 对象)的值为 0x0(nil)。

以下是问题分析和修复方案:

问题分析

redis.go 文件中,RedisPool 是一个全局变量:

var RedisPool *redis.Pool

但在代码中,这个变量可能在使用前没有被初始化,或者初始化失败。当调用 RedisPool.Get() 时,由于 RedisPool 是 nil,导致解引用空指针。

修复方案

1. 确保初始化 Redis 连接池

redis.go 中添加初始化函数,并确保在使用前调用:

package redis

import (
	"fmt"
	"log"
	"time"

	"github.com/gomodule/redigo/redis"
)

var RedisPool *redis.Pool

// InitRedisPool 初始化 Redis 连接池
func InitRedisPool(host, port, password string, db int) error {
	RedisPool = &redis.Pool{
		MaxIdle:     10,
		MaxActive:   100,
		IdleTimeout: 240 * time.Second,
		Dial: func() (redis.Conn, error) {
			address := fmt.Sprintf("%s:%s", host, port)
			c, err := redis.Dial("tcp", address)
			if err != nil {
				return nil, err
			}
			if password != "" {
				if _, err := c.Do("AUTH", password); err != nil {
					c.Close()
					return nil, err
				}
			}
			if _, err := c.Do("SELECT", db); err != nil {
				c.Close()
				return nil, err
			}
			return c, nil
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			if time.Since(t) < time.Minute {
				return nil
			}
			_, err := c.Do("PING")
			return err
		},
	}
	
	// 测试连接
	conn := RedisPool.Get()
	defer conn.Close()
	_, err := conn.Do("PING")
	return err
}

// GetConn 安全获取连接
func GetConn() (redis.Conn, error) {
	if RedisPool == nil {
		return nil, fmt.Errorf("redis pool not initialized")
	}
	return RedisPool.Get(), nil
}

2. 在 main.go 中正确初始化

package main

import (
	"fmt"
	"log"
	"gitlab.com/harish/calls/redis"
)

func main() {
	// 初始化 Redis 连接池
	err := redis.InitRedisPool("localhost", "6379", "", 0)
	if err != nil {
		log.Fatalf("Failed to initialize Redis pool: %v", err)
	}
	
	// 使用 Redis
	conn, err := redis.GetConn()
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	
	// 执行 Redis 操作
	_, err = conn.Do("SET", "key", "value")
	if err != nil {
		log.Fatal(err)
	}
	
	value, err := redis.String(conn.Do("GET", "key"))
	if err != nil {
		log.Fatal(err)
	}
	
	fmt.Printf("Got value: %s\n", value)
}

3. 添加安全检查

在使用 RedisPool 的任何地方都添加 nil 检查:

func SomeFunction() error {
	if redis.RedisPool == nil {
		return fmt.Errorf("redis pool is not initialized")
	}
	
	conn := redis.RedisPool.Get()
	defer conn.Close()
	
	// ... 其他操作
	return nil
}

关键点

  1. 全局变量初始化:确保 RedisPool 在第一次使用前被正确初始化
  2. 错误处理:初始化函数应返回错误,调用方需要处理这些错误
  3. 延迟初始化:考虑使用 sync.Once 确保只初始化一次:
var (
	RedisPool *redis.Pool
	once      sync.Once
)

func InitRedisPoolOnce(host, port, password string, db int) error {
	var initErr error
	once.Do(func() {
		initErr = InitRedisPool(host, port, password, db)
	})
	return initErr
}

这样修复后,可以避免空指针解引用错误,并确保 Redis 连接池在使用前已正确初始化。

回到顶部