[返回编程技术首页]·[所有跟帖]·[ 回复本帖 ] ·[热门原创] ·[繁體閱讀]·[坛主管理]

Go语言基础系列:深入理解和应用空接口

送交者: wecode[☆★声望品衔8★☆] 于 2024-06-29 15:09 已读 522 次  

wecode的个人频道

+关注
空接口

空接口是指没有定义任何接口方法的接口。没有定义任何接口方法,意味着Go中的任意对象都可以实现空接口(因为没方法需要实现),任意对象都可以保存到空接口实例变量中。


空接口的定义方式:


type


empty_int interface {

}

通常会简写为type empty_int interface{}。


更常见的,会直接使用interface{}作为一种类型,表示空接口。例如:


// 声明一个空接口实例


var


i


interface


{}

再比如函数使用空接口类型参数:


funcmyfunc


(i


interface


{})

在Go中很多地方都使用空接口类型的参数,用的最多的fmt中的Print类方法:


$


go


doc fmt Println

funcPrintln


(a ...


interface


{}) (n


int


, err


error


)

空接口数据结构

可以定义一个空接口类型的array、slice、map、struct等,这样它们就可以用来存放任意类型的对象,因为任意类型都实现了空接口。


例如,创建一个空接口的slice:


package


main

import"fmt"

funcmain


() {

any :=


make


([]


interface


{},


5


)

any[


0


] =


11


any[


1


] =


"hello world"


any[


2


] = []


int


{


11


,


22


,


33


,


44


}

for


_, value :=


range


any {

fmt.Println(value)

}

}

输出结果:


11


hello world

[


11223344


]

显然,通过空接口类型,Go也能像其它动态语言一样,在数据结构中存储任意类型的数据。


再比如,某个struct中,如果有一个字段想存储任意类型的数据,就可以将这个字段的类型设置为空接口:


type


my_struct


struct


{

anything


interface


{}

anythings []


interface


{}

}

拷贝数据结构到空接口数据结构

前面解释了任意类型的对象都能赋值给空接口实例。


varanyinterface


{}

any


=


"hello world"


any


=


11


空接口是一种接口,它是一种指针类型的数据类型,虽然不严谨,但它确实保存了两个指针,一个是对象的类型(或iTable),一个是对象的值。所以上面的赋值过程是让空接口any保存各个数据对象的类型和对象的值。


换一种角度考虑,空接口有自己的内存布局方式:两个指针,占用两个机器字长。


Golang给的一个经典的示例:将某个slice中的数据拷贝到空接口slice中将报错。


package


main

import"fmt"

funcmain


() {

testSlice := []


int


{


11


,


22


,


33


,


44


}

// 成功拷贝


var


newSlice []


int


newSlice = testSlice

fmt.Println(newSlice)

// 拷贝失败


var


any []


interface


{}

any = testSlice

fmt.Println(any)

}

这是因为每个空接口的内存布局都占用两个机器字长的内容。对于长度为N的空接口slice来说,它的每个元素都是以2机器字长为单元的连续空间,共占用N*2个机器字长的空间。


而普通的slice,例如上面的testSlice,它的每个元素是int类型的,int类型的内存布局和空接口不一样。


这些对象的内存布局在编译期间就已经确定好了,所以没法直接将不同内存布局的数据结构进行拷贝。


要想完成期待的拷贝,可以使用for-range的方式,将testSlice中的每个元素赋值给空接口slice的空接口元素:也就是一个个的空接口实例。


var


any []


interface


{}

for


_,value :=


range


testSlice{

any =


append


(any,value)

}

这样,空接口Slice中的每个空接口实例都指向更底层的各个数据对象。而不是像前面错误的拷贝方式:每个空接口元素想要当作这些数据对象。


不仅空接口的Slice如此,其它包含空接口的数据结构,也都类似。

喜欢wecode朋友的这个贴子的话, 请点这里投票,“赞”助支持!

内容来自网友分享,若违规或者侵犯您的权益,请联系我们

所有跟帖:   ( 主贴楼主有权删除不文明回复,拉黑不受欢迎的用户 )


用户名: 密码: [--注册ID--]

标 题:

粗体 斜体 下划线 居中 插入图片插入图片 插入Flash插入Flash动画


     图片上传  Youtube代码器  预览辅助



[ 留园条例 ] [ 广告服务 ] [ 联系我们 ] [ 个人帐户 ] [ 创建您的定制新论坛频道 ] [ Contact us ]