广告
返回顶部
首页 > 资讯 > 后端开发 > GO >golang中的nil接收器详解
  • 852
分享到

golang中的nil接收器详解

2024-04-02 19:04:59 852人浏览 独家记忆
摘要

我们先看一个简单的例子,我们自定义一个错误,用来把多个错误放在一起输出: type CustomError struct {errors []string} func (c *Cus

我们先看一个简单的例子,我们自定义一个错误,用来把多个错误放在一起输出:

type CustomError struct {
errors []string
}

func (c *CustomError) Add(err string) {
c.errors = append(c.errors, err)
}

func (c *CustomError) Error() string {
return strings.Join(c.errors, ";")
}

因为实现了Error() string方法,所以它实现了error接口。

现在我们要实现一个添加课件的功能,但是添加之前需要验证参数的合法性,所以我们创建了一个Validate方法,我们可能会这么写:

package main

import (
	"errors"
	"fmt"
	"strings"
)

type CustomError struct {
	errors []string
}

func (c *CustomError) Add(err error) {
	c.errors = append(c.errors, err.Error())
}

func (c *CustomError) Error() string {
	return strings.Join(c.errors, ";")
}

type Courseware struct {
	Name string
	Code string
}

func (c *Courseware) Validate() error {
	var m *CustomError // 1
	if c.Name == "" { // 2
		m = &CustomError{}
		m.Add(errors.New("课件名不能为空"))
	}
	if c.Code == "" { // 3
		if m == nil {
			m = &CustomError{}
		}
		m.Add(errors.New("课件编号不能为空"))
	}

	return m // 4
}

func main() {
	m := Courseware{
		Name: "多媒体课件",
		Code: "CW330",
	}
	if err := m.Validate(); err != nil {
		fmt.Println("valid err: ", err)
	}
}

看上去好像一点问题都没有:

  • 定义一个CustomError类型的指针
  • 如果Name为空,初始化m,调用Add方法把错误添加到CustomError.errors
  • 如果Code为空,如果m还没有初始化,先初始化,调用Add方法把错误添加到CustomError.errors
  • 最后返回自定义错误

但是当我们执行上面的代码时,会发现结果并不是我们想要的:

Go run 8.go
valid err:  <nil>

我们发现居然走到了打印错误的判断里,但是打印出来的错误居然是一个nil

在 Go 中,我们必须知道指针接收器可以为 nil。我们看一个简单的例子:

package main

import (
	"fmt"
)

type Demo struct {
}

func (d *Demo) Print() string {
	return "demo"
}

func main() {
	var d *Demo
	fmt.Println(d)
	fmt.Println(d.Print())
}
go run 8.go
<nil>
demo

Demo被初始化为nil,但是这段代码可以正常运行。说明nil指针也可以作为接收器。

其实上面的Print方法等价于:

func Print(d *Demo) string {
	return "demo"
}

因为将 nil 指针传递给函数是有效的。 所以使用 nil 指针作为接收器也是有效的。

我们继续回到上面的自定义错误。

m 被初始化为指针的零值:nil。 如果所有验证都通过,return 语句返回的结果不是 nil,而是一个 nil 指针。 因为 nil 指针是一个有效的接收器,所以将结果转换为error接口不会产生 nil 值。

所以我们虽然返回了一个nil指针,但是转换为error接口时并不是一个nil的接口(虽然是nil指针,但是是*CustomError类型,并实现了error)。

要解决这个问题,我们只要直接返回nil值,不返回nil的指针:

package main

import (
	"errors"
	"fmt"
	"strings"
)

type CustomError struct {
	errors []string
}

func (c *CustomError) Add(err error) {
	c.errors = append(c.errors, err.Error())
}

func (c *CustomError) Error() string {
	return strings.Join(c.errors, ";")
}

type Courseware struct {
	Name string
	Code string
}

func (c *Courseware) Validate() error {
	var m *CustomError
	if c.Name == "" {
		m = &CustomError{}
		m.Add(errors.New("课件名不能为空"))
	}
	if c.Code == "" {
		if m == nil {
			m = &CustomError{}
		}
		m.Add(errors.New("课件编号不能为空"))
	}

  // 这里如果m指针为nil,直接返回nil
	if m == nil {
		return nil
	}

	return m
}

func main() {
	m := Courseware{
		Name: "多媒体课件",
		Code: "CW330",
	}

	if err := m.Validate(); err != nil {
		fmt.Println("valid err: ", err)
	}
}

或者我们直接返回*CustomError类型的错误:

package main

import (
	"errors"
	"fmt"
	"strings"
)

type CustomError struct {
	errors []string
}

func (c *CustomError) Add(err error) {
	c.errors = append(c.errors, err.Error())
}

func (c *CustomError) Error() string {
	return strings.Join(c.errors, ";")
}

type Courseware struct {
	Name string
	Code string
}

// 返回*CustomError
func (c *Courseware) Validate() *CustomError {
	var m *CustomError
	if c.Name == "" {
		m = &CustomError{}
		m.Add(errors.New("课件名不能为空"))
	}
	if c.Code == "" {
		if m == nil {
			m = &CustomError{}
		}
		m.Add(errors.New("课件编号不能为空"))
	}

	return m
}

func main() {
	m := Courseware{
		Name: "多媒体课件",
		Code: "CW330",
	}

	if err := m.Validate(); err != nil {
		fmt.Println("valid err: ", err)
	}
}

但这并不是可取的,为了扩展我们实现了error接口,也需要返回error类型的错误。

到此这篇关于golang中的nil接收器的文章就介绍到这了,更多相关golangnil接收器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: golang中的nil接收器详解

本文链接: https://www.lsjlt.com/news/121253.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • golang中的nil接收器详解
    我们先看一个简单的例子,我们自定义一个错误,用来把多个错误放在一起输出: type CustomError struct {errors []string} func (c *Cus...
    99+
    2022-11-11
  • golang中的空接口使用详解
    目录1、空接口2、类型断言3、结构体值接收者和指针接收者实现接口的区别4、一个结构体实现多个接口5、接口嵌套6、Golang中空接口和类型断言使用细节1、空接口 Golang 中的接...
    99+
    2022-11-12
  • Android 广播接收器BroadcastReceiver详解
    目录一、什么是BroadcastReceiver1.1、作用1.2、实现原理二、创建广播接收器三、注册广播接收器3.1、静态注册注册发送通知3.2、动态注册四、系统广播总结一、什么是...
    99+
    2022-11-13
  • Go中的nil切片和空切片区别详解
    Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0。 字符串变量的默认值为空字符串。 ...
    99+
    2022-06-07
    nil GO
  • 一文详解Go中方法接收器的选择
    目录前言方法接收器值接收器指针接收器值接收器与指针接收器的比较如何选择正确的方法接收器选择原则实际开发中的一些建议小结前言 许多 Go 初学者在方法接收器的选择上...
    99+
    2023-05-17
    Go方法接收器的选择 Go方法接收器 Go指针接收器 Go值接收器 Go接收器
  • Android之 BroadcastReceiver广播接收器详解
    一 四大组件 1 Activity组件,它一个单独的窗口,程序流程都必须在Activity中运行。 2 service组件,用于在后台完成用户指定的操作。 3 content provider组件,会为所有的应用准备一个内容窗口,并且保留数...
    99+
    2023-09-22
    android
  • 阿里云接收邮件的服务器详解
    阿里云是阿里巴巴集团旗下的云计算品牌,提供包括云计算、数据库、存储、安全、物联网、人工智能等全面的云计算服务。作为阿里云的一个重要组成部分,阿里云接收邮件的服务器具有稳定、高效、安全的特点,为用户提供了优质的邮件服务。本文将详细介绍阿里云接...
    99+
    2023-12-10
    阿里 详解 接收邮件
  • Golang中的Interface详解
    背景: golang的interface是一种satisfied式的。A类只要实现了IA interface定义的方法,A就satisfied了接口IA。更抽象一层,如果某些设计上需...
    99+
    2022-11-13
  • Golang设计模式中的桥接模式详细讲解
    目录桥接模式概念示例桥接模式 桥接是一种结构型设计模式, 可将业务逻辑或一个大类拆分为不同的层次结构, 从而能独立地进行开发。 层次结构中的第一层 (通常称为抽象部分) 将包含对第二...
    99+
    2023-01-11
    Go桥接模式 Go设计模式
  • Golang 中的 unsafe.Pointer 和 uintptr详解
    目录前言uintptrunsafe.Pointer使用姿势常规类型互转Pointer => uintptr指针算数计算:Pointer => uintptr => ...
    99+
    2022-11-11
  • 深入Golang中的sync.Pool详解
    我们通常用golang来构建高并发场景下的应用,但是由于golang内建的GC机制会影响应用的性能,为了减少GC,golang提供了对象重用的机制,也就是sync.Pool对象池。 ...
    99+
    2022-11-12
  • Golang开发之接口的具体使用详解
    目录Golang的接口是什么什么情况下要用接口实战案例多态的例子定义通用方法的例子松耦合的例子实现插件化架构的例子Golang的接口是什么 在 Golang 中,接口是一种类型,它是...
    99+
    2023-05-14
    Golang接口使用 Golang接口 Go 接口
  • springbootudp或者tcp接收数据的实例详解
    下面用的是 springboot内置integration依赖 <dependency> <groupId>org.springf...
    99+
    2022-11-12
  • Springboot接收 Form 表单数据的示例详解
    目录一、接收 Form 表单数据1,基本的接收方法2,参数没有传递的情况3,使用 map 来接收参数4,接收一个数组5,使用对象来接收参数6,使用对象接收时指定参数前缀二、接收字符串...
    99+
    2022-11-13
    Springboot接收表单数据 Springboot表单数据
  • Struts2之Action接收请求参数和拦截器详解
    技术分析之在Struts2框架中使用Servlet的API1. 在Action类中也可以获取到Servlet一些常用的API需求:提供JSP的表单页面的数据,在Action中使用Servlet的API接收到,然后保存到三个域对象中,最后再显...
    99+
    2023-05-31
    struts 拦截 action
  • Golang函数的接口和访问控制的详解
    Golang作为一门快速、高效的编程语言,广受开发者的青睐。在Golang中,函数是非常重要的组成部分,函数可以是公共的,也可以是私有的。在本文中,我们将会深入探讨Golang函数的接口和访问控制,以便更好地理解Golang的开发模式和最佳...
    99+
    2023-05-16
    Golang 函数接口 访问控制
  • Golang中指针的使用详解
    目录1.概念2.指针定义与空指针3.指针赋值与取值4.切片指针5.指针的指针1.概念 指针:指向内存地址的变量,指针用来存储变量的内存地址 Go 语言定义变量必须声明数据类型,因为不...
    99+
    2023-05-18
    Golang指针 Go指针类型
  • 详解golang中的闭包与defer
    目录闭包与defer1.闭包2.defer闭包与defer 1.闭包 闭包 : 一个函数与其相关的引用环境组合的一个实体,其实可以理解为面向对象中类中的属性与方法。如代码块中,函数f...
    99+
    2022-11-11
  • 一文详解Golang中的反射
    本篇文章带大家主要来聊聊Golang中反射,希望对你有新的认知。虽然很多人使用 Go 语言有一定时间了,甚至有的使用了 1 年 2 年,然后对于 Go 语言中的反射还是模棱两可,使用起来的时候,心里也不是非常有底气。【相关推荐:Go视频教程...
    99+
    2023-05-14
    反射 go语言 Golang
  • 一文详解golang中的注释
    Golang是一种编程语言,它有着比较高的代码可读性和简洁性。然而,在编写代码时,总有些地方需要添加注释来帮助解释某些细节或者增加代码的可读性。在这篇文章中,我们将介绍一些关于Golang注释的内容。一、单行注释单行注释是在代码行的末尾添加...
    99+
    2023-05-14
    go语言 Golang 注释
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作