iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Golang怎么自定义类型和方法集
  • 299
分享到

Golang怎么自定义类型和方法集

2023-07-05 04:07:12 299人浏览 独家记忆
摘要

这篇文章主要介绍“golang怎么自定义类型和方法集”,在日常操作中,相信很多人在Golang怎么自定义类型和方法集问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang怎么自定义类型和方法集”的疑惑有所

这篇文章主要介绍“golang怎么自定义类型和方法集”,在日常操作中,相信很多人在Golang怎么自定义类型和方法集问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang怎么自定义类型和方法集”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

我们先以一个谜题开头练练手:

package main import (    "encoding/JSON"    "fmt"    "time") type MyTime time.Time func main() {    myTime := MyTime(time.Now()) // 假设获得的时间是 2022年7月20日20:30:00,时区UTC+8    res, err := json.Marshal(myTime)    if err != nil {        panic(err)    }    fmt.Println(string(res))}

请问上述代码会输出什么:

编译错误

运行时panic

{}

"2022-07-20T20:30:00.135693011+08:00"

很多人一定会选4吧,然而答案是3:

$ go run customize.go
 
{}

是不是很意外,MyTime就是time.Time,理论上应该也实现了json.Marshaler,为什么输出的是空的呢?

实际上这是最近某个群友遇到的问题,乍一看像是golang的bug,但其实还是没掌握语言的基本规则。

在深入下去之前,我们先问自己两个问题:

  • MyTime 真的是 Time 类型吗?

  • MyTime 真的实现了 json.Marshaler 吗?

对于问题1,只需要引用spec里的说明即可:

A named type is always different from any other type.

https://go.dev/ref/speC#Type_identity

意思是说,只要是type定义出来的类型,都是不同的(type alias除外),即使他们的underlying type是一样的,也是两个不同的类型。

那么问题1的答案就知道了,显然MyTime不是time.Time。

既然MyTime不是Time,那它是否能用Time类型的method呢?毕竟MyTime的基底类型是Time呀。我们写段代码验证下:

package main import (    "fmt"    "time") type MyTime time.Time func main() {    myTime := MyTime(time.Now()) // 假设获得的时间是 2022年7月20日20:30:00,时区UTC+8    res, err := myTime.MarsharlJSON()    if err != nil {            panic(err)    }    fmt.Println(string(res))}

运行结果:

# command-line-arguments
./checkoutit.go:12:24: myTime.MarsharlJSON undefined (type MyTime has no field or method MarsharlJSON)

现在问题2也有答案了:MyTime没有实现json.Marshaler。

那么对于一个没有实现json.Marshaler的类型,json是怎么序列化的呢?这里就不卖关子了,文档里有写,对于没实现Marshaler的类型,默认的流程使用反射获取所有非export的字段,然后依次序列化,我们再看看time的结构:

type Time struct {        // wall and ext encode the wall time seconds, wall time nanoseconds,        // and optional monotonic clock reading in nanoseconds.        //        // From high to low bit position, wall encodes a 1-bit flag (hasMonotonic),        // a 33-bit seconds field, and a 30-bit wall time nanoseconds field.        // The nanoseconds field is in the range [0, 999999999].        // If the hasMonotonic bit is 0, then the 33-bit field must be zero        // and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext.        // If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit        // unsigned wall seconds since Jan 1 year 1885, and ext holds a        // signed 64-bit monotonic clock reading, nanoseconds since process start.        wall uint64        ext  int64         // loc specifies the Location that should be used to        // determine the minute, hour, month, day, and year        // that correspond to this Time.        // The nil location means UTC.        // All UTC times are represented with loc==nil, never loc==&utcLoc.        loc *Location}

里面都是非公开字段,所以直接序列化后整个结果就是{}。当然,Time类型自己重新实现了json.Marshaler,所以可以正常序列化成我们期望的值。

而我们的MyTime没有实现整个接口,所以走了默认的序列化流程。

所以我们可以得出一个重要的结论:从某个类型A派生出的类型B,B并不能获得A的方法集中的任何一个。

想要B拥有A的所有方法也不是不行,但得和type B A这样的形式说再见了。

方法一是使用type alias:

- type MyTime time.Time+ type MyTime = time.Time func main() {-   myTime := MyTime(time.Now()) // 假设获得的时间是 2022年7月20日20:30:00,时区UTC+8+   var myTime MyTime = time.Now() // 假设获得的时间是 2022年7月20日20:30:00,时区UTC+8    res, err := json.Marshal(myTime)    if err != nil {        panic(err)    }    fmt.Println(string(res))}

类型别名自如其名,就是创建了一个类型A的别名而没有定义任何新类型(注意那两行改动)。现在MyTime就是Time了,自然也可以直接利用Time的MarshalJSON。

方法二,使用内嵌类型:

- type MyTime time.Time+ type MyTime struct {+     time.Time+ } func main() {-   myTime := MyTime(time.Now()) // 假设获得的时间是 2022年7月20日20:30:00,时区UTC+8+   myTime := MyTime{time.Now}    res, err := myTime.MarsharlJSON()    if err != nil {            panic(err)    }    fmt.Println(string(res))}

通过将Time嵌入MyTime,MyTime也可以获得Time类型的方法集。更具体的可以看我之前写的另一篇文章:golang拾遗:嵌入类型

如果我实在需要派生出一种新的类型呢,通常在我们写一个通用模块的时候需要隐藏实现的细节,所以想要对原始类型进行一定的包装,这时该怎么办呢?

实际上我们可以让MyTime重新实现json.Marshaler:

type MyTime time.Time func (m MyTime) MarshalJSON() ([]byte, error) {    // 我图方便就直接复用Time的了    return time.Time(m).MarshalJSON()} func main() {    myTime := MyTime(time.Now()) // 假设获得的时间是 2022年7月20日20:30:00,时区UTC+8    res, err := myTime.MarsharlJSON()    if err != nil {            panic(err)    }    fmt.Println(string(res))}

这么做看上去违反了DRY原则,其实未必,这里只是示例写的烂而已,真实场景下往往对派生出来的自定义类型进行一些定制,因此序列化函数里会有额外的一些操作,这样就和DRY不冲突了。

不管哪一种方案,都可以解决问题,根据自己的实际需求做选择即可。

到此,关于“Golang怎么自定义类型和方法集”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

您可能感兴趣的文档:

--结束END--

本文标题: Golang怎么自定义类型和方法集

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

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

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

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

下载Word文档
猜你喜欢
  • Golang怎么自定义类型和方法集
    这篇文章主要介绍“Golang怎么自定义类型和方法集”,在日常操作中,相信很多人在Golang怎么自定义类型和方法集问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Golang怎么自定义类型和方法集”的疑惑有所...
    99+
    2023-07-05
  • Golang拾遗之自定义类型和方法集详解
    golang拾遗主要是用来记录一些遗忘了的、平时从没注意过的golang相关知识。 很久没更新了,我们先以一个谜题开头练练手: package main import ( ...
    99+
    2023-02-20
    Golang自定义类型 方法集 Golang自定义类型 Golang 方法集
  • golang方法类型定义
    Golang是一门非常强大的编程语言,其支持面向对象编程(OOP)的方式。在Golang中,我们可以使用方法(Method)来实现面向对象编程中的封装、继承和多态等特性。方法是指与某个类型相关联的函数,可以通过类型进行调用,类似于其他编程语...
    99+
    2023-05-15
  • 怎么在Golang中转换自定义类型
    怎么在Golang中转换自定义类型?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。golang适合做什么golang可以做服务器端开发,但golang很适合做日志...
    99+
    2023-06-06
  • Mybatis-Plus怎么自定义集合类型的类型处理器
    这篇文章主要讲解了“Mybatis-Plus怎么自定义集合类型的类型处理器”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Mybatis-Plus怎么自定义集合类型的类型处理器”吧!1.配合x...
    99+
    2023-06-26
  • 自定义golang函数错误类型
    是的,在 go 中可以定义自定义错误类型,通过创建实现 error 接口的结构体,并提供 error() 方法返回错误消息。自定义错误类型可以使用 errors.new 函数或自定义类型...
    99+
    2024-05-02
    golang 函数类型 关键词
  • VB.NET中怎么自定义类型
    VB.NET中怎么自定义类型,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。VB.NET自定义类型在VB.NET中称为“structure”(结构),包含有一个或多个不同种类的数...
    99+
    2023-06-17
  • golang如何自定义返回值类型?
    go 语言中可通过创建自定义类型定义函数返回值,增强灵活性,允许返回特定格式或结构的数据。通过 syntax:func functionname() (returntype1, retu...
    99+
    2024-04-23
    golang 自定义返回值类型
  • C#中怎么定义和使用泛型类和方法
    在C#中,泛型类和方法可以让你编写更加灵活和可复用的代码。以下是如何定义和使用泛型类和方法的示例: 定义泛型类: public cl...
    99+
    2024-03-06
    C#
  • C++自定义数据类型方法详情
    目录1、typedef声明2、枚举类型enum1、typedef声明 typedef用于给已有的类型一个新的名字,这个新的名字可以是自己定义的, 其语法为: typedef 现有类型...
    99+
    2024-04-02
  • 在Golang中实现自定义错误类型
    在 go 中创建自定义错误类型可提供更详细的错误消息。创建自定义错误类型:用 error 接口定义错误类型,实现 error() 方法返回错误消息。使用自定义错误类型:像使用任何其他错误...
    99+
    2024-04-15
    golang 关键词
  • Mybatis-Plus自定义集合类型的类型处理器详解
    目录1.配合xml文件2.手动注册两种方法,第一种很麻烦,对mp自带的插入操作有限制,后来改为更简洁的第二种方法 1.配合xml文件 TypeHandler @Slf4j @Map...
    99+
    2024-04-02
  • .NET 6中为record类型自定义Equals方法
    目录一、重写Equals方法二、自定义Equals方法三、结论前言: record类型,这是一种新引用类型,而不是类或结构。record与类不同,区别在于record类型使用基于值的...
    99+
    2024-04-02
  • springmvc怎么自定义类型转换器
    要自定义类型转换器,首先需要创建一个实现了Converter接口的转换器类,然后在Spring MVC的配置文件中注册这个转换器。 ...
    99+
    2024-04-02
  • Python 中怎么自定义基本类型
    本篇文章为大家展示了Python 中怎么自定义基本类型,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。我们也知道,在 Python 里面,一切都是对象,而对象一般有方法。所以,大家会看到下面这种写法:...
    99+
    2023-06-16
  • Golang中的方法怎么定义和使用
    这篇文章主要介绍“Golang中的方法怎么定义和使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang中的方法怎么定义和使用”文章能帮助大家解决问题。方法语法在Golang中,方法定义的语法...
    99+
    2023-07-05
  • Golang同名方法怎么定义和使用
    这篇文章主要介绍了Golang同名方法怎么定义和使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Golang同名方法怎么定义和使用文章都会有所收获,下面我们一起来看看吧。同名方法的定义在Golang中,同名方...
    99+
    2023-07-05
  • Java怎么自定义强制类型转换
    在Java中,可以使用自定义方法来实现强制类型转换。下面是一个示例:```javapublic class MyClass {pub...
    99+
    2023-09-27
    Java
  • 如何在 Golang 中使用自定义错误类型?
    非常抱歉,由于您没有提供文章标题,我无法为您生成一篇高质量的文章。请您提供文章标题,我将尽快为您生成一篇优质的文章。...
    99+
    2024-05-14
  • 怎么在C语言中自定义类型
    本篇文章为大家展示了怎么在C语言中自定义类型,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、初始结构体结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。下面举一个例子:s...
    99+
    2023-06-08
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作