首页 > 其他分享 >go 类型别名

go 类型别名

时间:2023-03-18 14:11:36浏览次数:26  
标签:重构 代码 oldpkg 别名 类型 OldType go Go

1. 背景

类型别名(type aliases)原本是要在 Go 1.8 发布时推出的。但是由于一些争议和实现上的问题,Go 团队把它推迟到了 Go 1.9。

2.目的

这一特性其实是为开发者们的代码库重构准备的。代码重构是对代码的重新组织,以及这种重组与代码包之间的关系的重新思考和修改过程。代码重构的原因可能是代码的拆分、命名优化或者依赖关系清理,等等。但是不论原因是什么,我们的目的都是让代码变得更清楚、更易于使用,以及更容易扩展。

也许你有过这样的经历:在进行(范围比较广的)代码重构的过程中,原有代码已经改变。甚至,当你完成重构并想把代码合并回去的时候,原有代码已经面目全非。合并代码有时候比重构代码更加困难。

 

这就引出了一个比较先进的重构方法——渐进式代码重构。也就是说,同时计划重构的终极目标和阶段性目标。在达到完备状态之前,设置几个易实施并且可用的中间状态。纵观 Go 语言的代码更新和版本升级过程,我们不难发现 Go 团队对这种方法的合理运用。

然而,在渐进式代码重构的过程中我们也可能会遇到问题。例如,当你想把一个允许包外代码访问的类型迁移到另外一个包中时,该怎么做?简单来说,应该分为三步:

1)在目的包中声明一个名称和功能都相同的新类型。

2)检查所有可能引用原类型的地方,并把那些引用都指向新类型。

3)删除原包中的那个类型。如果这个类型只被由你掌控的程序中引用,那么这种方式当然没问题。

但是,如果该类型所在的是一个已被广泛依赖的底层代码包,那我劝你还是不要执行第 3 步了。

除非你冒着被口水淹死的风险发布程序不兼容声明。可是不执行第 3 步就等于任由废弃代码在程序中蔓延。

这也是很恶心的一件事。

 

讲了这么多,我要说的重点是:Go 的类型别名就是为我们解决这类两难的问题的。在类型别名真正问世之前,Go 团队自己在做上述重构时都不得不用上一些特殊的、脆弱的手段。

 

3.eg

 

若使用类型别名的话,应该怎么做?

如果我们要把 oldpkg.OldType 类型迁移到 newpkg 代码包中并将其改名为 NewType,那么最少用 2 步就可以完成:

1)声明 newpkg.NewType 类型。

2)把 oldpkg.OldType 类型的声明改为:

 

package oldpkg
type OldType = newpkg.NewType

 

新的 oldpkg.OldType 类型声明可以使它与 newpkg.NewType 完全等价,并可以实现互换。也就是说,如果一个函数有一个 oldpkg.OldType 类型的参数声明,那么该函数就可以接受一个 newpkg.NewType 类型的参数值。

 

当然,为了不留废弃代码你仍然需要在某个时间删除掉 oldpkg.OldType。

但是类型别名给了你和其他使用 oldpkg.OldType 的开发者一个可以游刃有余的必要条件。

你们为重构代码而设置的中间状态都可以轻松达成。

举个例子,你在按照上述 2 步迁移完类型之后,可以马上把自己写的某个函数的声明由

 

package handler
import oldpkg
func HandleXXX(obj oldpkg.OldType){}

  改为

package handler
import newpkg
func HandleXXX(obj newpkg.NewType){}

 

然而,在调用该函数的(其他人写的)程序那里,却可以不用做任何修改(虽然最后可能要修改)。

代码 handler.HandleXXX(oldTypeVar) 仍然有效。其中的 oldTypeVar 是 oldpkg.OldType 类型的值。这就相当于可以让各方按照自己的节奏重构代码了。

 

再后面的情景可能是:你在你的代码包还是 1.0 版本的时候就发布声明说 oldpkg.OldType 类型即将在 2.0 版本中删除。而当你在开发 2.0 版本时,心安理得地删掉了 oldpkg.OldType。

 

实际上,类型别名只是 Go 团队为了让我们顺利实施大规模 Go 软件工程的举措之一。

他们一直在致力于帮助开发者们高效地编写 Go 代码和利用 Go 代码包,并避免因不经意的重复造轮子而导致的代码膨胀。

如果你真正用过 Go 语言,那么也一定能体会到它在代码依赖方面展现出的规范性和严谨性。

 

标签:重构,代码,oldpkg,别名,类型,OldType,go,Go
From: https://www.cnblogs.com/gongxianjin/p/17230530.html

相关文章

  • 过滤组件的使用--django_filter模块实现多条件组合查询
    1.过滤组件的使用(实现条件查询)_第一步_安装django_filter:  2.过滤组件的使用(实现条件查询),第二步:注册django_filters:  3.过滤组件的使用(实现条件查询),第三步:过......
  • 0008 ALGO999-数的潜能
    试题算法训练数的潜能可以转换为将数分解为多少个3,再处理余数即可。为什么不分解为2,因为23=8<9=32。加上较小值得处理,输入值\(\le4\)时,直接输出即可。......
  • 测试JUC安全类型的集合
    packageedu.wtbu;importjava.util.concurrent.CopyOnWriteArrayList;//测试JUC安全类型的集合publicclassDemo09{publicstaticvoidmain(String[]args){......
  • mysql 常用的数据类型
    官网文档地址:https://dev.mysql.com/doc/refman/8.0/en/data-types.html常用的数据类型:NumericDataTypesDateandTimeDataTypesStringDataTypes,SpatialData......
  • 【转载】集合中元素的数据类型可以不同,但集合中不能嵌套列表、元组、集合、字典
    1、问题根源:text={"a":{"aa":1,"b":2},"b":2,"c":3,"d":4,"e":5}list_dict=[{v:text[v]}forvintext]set(list_dict)输出:TypeError......
  • 数据类型转换、运算符
    day02数据类型太简单,没啥写的,略注意:空串""是长度为0的字符串。空串是一个Java对象,有自己的串长度(0)和内容(空)。不过,String变量还可以存放一个特殊的值,名为null,这表示目前......
  • 关于float和double类型数据在单片机内存中如何存储和转换
    关于float和double类型数据在单片机内存中如何存储和转换1、单精度浮点型float,双精度浮点型double数据在内存中的存储模型(1)下图为单精度浮点型数据float的存储模型,符号位......
  • java基础_基本数据类型
    介绍鄙人才疏学浅,如有谬论,敬请指教。计算机储存容量单位讲解计算机储存容量基本单位就是字节(Byte),而字节下面还有一个比特>(bit),对应关系是一个字节=八个比特,比特(bit......
  • django 迁移数据报错:django.db.utils.OperationalError: (1050, "Table 'xxx' alread
    方法1:登录数据库删除掉django创建数据表的所有数据内容、或者直接删掉所有表格。DROPTABLEtable_name;因为MySQL中设置了foreignkey关联,造成无法更新或删除数据。......
  • 钉钉消息类型汇总
    { "msgtype":"text", "text":{ "content":"我就是我,是不一样的烟火@156xxxx8827" }, "at":{ "atMobiles":[ "156xxxx8827", "189xxxx8325" ], "......