Golang 语言怎么避免空指针引发的 Panic

开发 后端
本文我们介绍一些 Golang 语言开发需要避免空指针引发 panic 的场景,虽然都比较简单,但是新手很容易踩“坑”。欢迎读者朋友们在评论区与大家分享更多因为触发空指针引发 panic 的场景。

01介绍

在 Golang 语言项目开发中,变量操作不当就会触发空指针引发程序 panic。空指针就是未分配内存的指针类型的变量,变量的值是 nil,因为操作空指针会引发 panic,所以我们在程序开发中要特别小心。

02结构体指针类型返回值

在调用结构体指针类型返回值的函数或方法时,并且需要操作返回值的字段或方法,此时,我们就需要注意触发空指针引发的 panic。

操作返回值的字段:

func main() { 
 user := GetUser() 
 fmt.Println(user
 fmt.Println(user.Id) 

 
func GetUser() (user *User) { 
 return 

 
type User struct { 
 Id   int 
 Name string 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

阅读上面这段代码,我们通过调用函数 GetUser() 获取 *User 类型的返回值,因为返回值变量是空指针,当我们访问返回值的字段时,程序引发 panic。

避免此类空指针问题,一是可以在返回值包含指针类型变量的函数或方法中,在函数体开头初始化返回值的指针类型变量;二是在调用结构体指针类型返回值的函数或方法时,在操作返回值的字段或方法时,先判定返回值是否为 nil(空指针)。

func main() { 
 user := GetUser() 
 fmt.Println(user
 if user != nil { 
  fmt.Println(user.Id) 
 } 

 
func GetUser() (user *User) { 
 user = new(User
 // user = &User{} 
 return 

 
type User struct { 
 Id   int 
 Name string 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

操作返回值的方法:

func main() { 
 user := GetUser() 
 user.Login() 

 
func GetUser() (user *User) { 
 return 

 
type User struct { 
 Id   int 
 Name string 

 
func (u User) Login() { 
 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

阅读上面这段代码,我们通过调用函数 GetUser() 获取 *User 类型的返回值,因为返回值变量是空指针,当我们访问返回值的方法 Login() 时,程序触发空指针引发 panic。

避免此类空指针问题,一是可以在返回值是指针类型变量的函数或方法的函数体中,开头先初始化返回值的指针类型变量;二是类型方法的接收者使用指针类型。

func main() { 
 user := GetUser() 
 user.Login() 

 
func GetUser() (user *User) { 
 user = new(User
 // user = &User{} 
 return 

 
type User struct { 
 Id   int 
 Name string 

 
func (u *User) Login() { 
 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

03结构体指针类型 value 的 Map

在 Golang 语言程序开发中,经常会操作结构体指针类型 value 的 Map,也需要注意触发空指针引发 panic。

func main() { 
 var userData map[int]*User 
 fmt.Println(userData[1].Name

 
type User struct { 
 Id   int 
 Name string 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

阅读上面这段代码,我们定义 map 类型的变量 userData,key 是 int 类型,value 是结构体指针类型,我们访问 map 的值时,因为值是空指针,所以会引发 panic。

避免此类空指针问题,我们可以使用 ok-idiom 模式判断键值是否存在,如果键值存在(判断键值是否为 nil),我们访问键值的字段,否则不访问。通过这种方式,也可以避免触发空指针引发 panic。

func main() { 
 var userData map[int]*User 
 if val, ok := userData[1]; ok { 
  fmt.Println(val.Name
 } 

 
type User struct { 
 Id   int 
 Name string 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

04defer 延迟调用

关键字 defer 延迟调用函数,虽然被调用函数会延迟调用,但是被调用函数的变量会先被注册。所以,如果被调用函数的变量是空指针,就会引发 panic。

func main() { 
 res, err := http.Get("http://www.baidu2022.com/robots.txt") // 伪造错误请求 
 defer res.Body.Close() 
 if err != nil { 
  log.Fatal(err) 
 } 
 body, err := io.ReadAll(res.Body) 
 if err != nil { 
  log.Fatal(err) 
 } 
 fmt.Printf("%s", body) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

阅读上面这段代码,使用 defer 延迟调用函数释放资源,因为我们将 defer 放在错误检查之后,所以如果返回值 res 是空指针,就会引发 panic。

避免此类空指针问题,我们可以在使用 defer 调用之前,先做错误检查,并且遇到错误后停止向下执行。

05总结

 

本文我们介绍一些 Golang 语言开发需要避免空指针引发 panic 的场景,虽然都比较简单,但是新手很容易踩“坑”。欢迎读者朋友们在评论区与大家分享更多因为触发空指针引发 panic 的场景。

 

责任编辑:武晓燕 来源: Golang语言开发栈
相关推荐

2021-12-13 01:24:14

语言Golang panic

2023-10-08 11:09:22

Optional空指针

2015-07-30 10:12:32

JavaNullAssert

2022-01-09 23:04:19

语言打印结构体

2021-06-09 23:36:46

Golang语言版本

2021-09-13 05:02:49

GogRPC语言

2021-06-07 23:19:44

Golang语言 Defer

2023-09-07 08:05:32

三元表达式自动

2021-10-10 23:02:49

Golang语言代码

2025-03-12 12:03:10

2021-06-29 23:40:19

Golang语言并发

2021-11-15 06:56:45

系统运行空指针

2021-11-08 23:09:07

Go排序数据

2021-07-12 05:05:59

Golang语言字段

2021-01-29 08:56:13

Golang标准库函数

2021-01-13 06:58:35

C语言函数指针

2022-01-19 09:00:00

Java空指针开发

2023-07-04 08:56:07

指针类型Golang

2025-03-31 00:29:44

2023-10-09 07:14:42

panicGo语言
点赞
收藏

51CTO技术栈公众号