Skip to content

20210101关于golang数据类型的强制转换,尤其是接口与接口之间,函数变量与函数变量之间

ziyouzy edited this page Jan 2, 2021 · 1 revision

首先,我们不会进行把一个函数变量强制转换成接口变量的操作

用户自己设计的数据类型,需要进行强制转换的操作,往往是在一个原始数据类型,与type后的别名数据类型之间的操作

而这可以分别举一个结构类的例子,再举一个函数类型的例子,应该可以清晰的说明问题:

结构类:

type testS struct{a int;b int}
type testNewS testS
func (p testS)testFunc(){fmt.Println("测试1")}
func (p testNewS)testFunc(){fmt.Println("测试2")}

var tns testNewS 

func main(){
ts :=testS{a :1,b :2}
//tns =testNewS(ts)
ts =testS(tns)

ts.testFunc()
tns.testFunc()
}

对于结构体而言,原始结构体与别名结构体可以实现完美的相互强制转换,但是不能继承转换前的方法,而转换后则会拥有目标结构体的方法,同时也是双向性的,不存在父子的不对等状态,原始结构体和别名结构体的地位是完全平等的

type testI interface{
testm1()string
testm2()int
}

type newTestI testI

而对于接口而言,灵活性则更高,首先明确一点,不能给接口定义方法!

同时也正因如此,原始接口变量和别名接口变量之间相互赋值并不需要强制转换

同时“被赋值”接口会拥有旧变量的field(各个字段的值),以及旧变量所属结构类的方法

只要满足基础与法规则,原始接口和别名接口的地位和结构体一样,是完全平等的,可以相互赋值

此外也和var int a =1;        var int b =2;       a =int(b)这个例子一样,对于接口来说强制转换无论是语法还是编译器都是允许的,只不过是没必要这么做

然而除了接口之外,即使是最基本的int,被type后也必须通过强制转换才能相互赋值

也就是说至少在这篇文章中,int为代表的基础数据类型、结构类、函数类型,都必须使用强制转换语法才能实现强制转换,于是大概像是切片,数组,map这样的复杂数据类型,被type后也需要使用强制转换语法,然而我想错了:

经测试,结构类必须采用强制转换语法(值类型)

经测试,基础数据类型(如int)必须采用强制转换语法,别名数据类型可以直接进行赋值操作,编译器是可以是别的((newi =123)不报错)(值类型)

----

经测试,map类型无论是别名函数原始类型都需要make后才可以进行各类操作,同时可以直接赋值,并不需要强制转换,似乎是因为引用类型都可以直接赋值,而值类型则必须要强制转换
即使给别名后的类型定义了方法也可以直接赋值,赋值后会和强制转换的情况一样,基于赋值目标结构体的构造对方法进行阉割或添加(引用类型)

核心对比(数组(值类型)和切片(引用类型))
经测试,对于数组来说,数组别名的赋值方法与旧数组的赋值方法相同([5]int{1,2,3,4,6}),但是和接口一样可以直接赋值,不需强制转换
经测试,对于切片来说,切片别名的赋值方法与旧切片的赋值方法相同([]int{1,2,3,4,6}),但是和接口一样可以直接赋值,不需强制转换
切片和接口在使用上是完全相同的,但是他们毕竟一个是值类型,一个是指针类型啊

似乎任何一种数据类型与这个数据类型的别名,这两者之间的类型匹配是和其是属于值类型还是引用类型、以及是属于基本数据类型还是高级数据类型,是完全没有关系的 每一种类型与类型别名的类型匹配,都是立属于这个类型自身的特性,没有规律可寻,每种类型都有属于自己的特性: int->必须强制转换 string->必须强制转换 以及其他基础类型->必须强制转换

结构类->必须强制转换

map->不必须
接口->不必须
数组->不必须
切片->不必须
管道->不必须
函数->不必须

同时任何函数的参数表也遵顼如上特性, 结构体依然比较特殊必须进行强制转换,同时如果取结构体的指针进行同样的操作,需要分为两步,第一部依然是先进行结构体值的强制转换,转换后再进行指针的相关操作,这其实不太算属于当前问题的探讨范畴

总结看来,似乎只有结构体是个特例,同时结构体也是唯一的值类型符合类型

Clone this wiki locally