当前位置: 首页 > news >正文

电商网站建设事例北京建工集团有限公司官网

电商网站建设事例,北京建工集团有限公司官网,20亿做网站,大佬做的魔法少女网站目录 前言✨一、什么是接口#xff1f;二、空接口 interface{}1、eface的定义2、需要注意的问题 三、非空接口1、iface的定义2、itab的定义3、itab缓存 前言✨ 前段时间忙着春招面试#xff0c;现在也算告一段落#xff0c;找到一家比较心仪的公司实习#xff0c;开始慢慢回… 目录 前言✨一、什么是接口二、空接口 interface{}1、eface的定义2、需要注意的问题 三、非空接口1、iface的定义2、itab的定义3、itab缓存 前言✨ 前段时间忙着春招面试现在也算告一段落找到一家比较心仪的公司实习开始慢慢回归状态这后面几章我会学习go1.19版本的语言特性或者机制类型系统、接口、断言以及反射的内容也算是补上之前没有深入底层的内容。 一、什么是接口 Go语言中的接口interface是一种类型它定义了一组方法的集合但没有具体的实现。接口可以被任何类型实现只要该类型实现了接口中定义的所有方法。这种设计方式使得Go语言具有很高的灵活性和可扩展性。 // 定义一个接口包含一个String方法 type Stringer interface {String() string }// 定义一个结构体实现Stringer接口 type Person struct {Name stringAge int }func (p Person) String() string {return fmt.Sprintf(%s (%d), p.Name, p.Age) }func TestInterface(t *testing.T) {// 定义一个接口变量只能存储实现了Stringer接口的值var str Stringer// str 42 // 编译错误int类型没有实现Stringer接口// str hello // 编译错误string类型没有实现Stringer接口str Person{Bob, 30}fmt.Println(str) // Bob (30) }Go语言接口的特点是 接口是一种抽象的类型它只定义了一组方法而不指定具体的实现。接口是隐式实现的也就是说任何类型只要实现了接口的所有方法就可以被认为是该接口的实例而不需要显式地声明。接口可以组合也就是说一个接口可以包含另一个接口的所有方法一个接口可以由多个接口的方法组成从而实现接口的多态。 Go语言接口的优点是 接口可以提高代码的复用性和可维护性因为它可以将不同类型的对象抽象为统一的接口从而降低了代码之间的耦合度。接口可以提高代码的灵活性和扩展性因为它可以支持多种实现方式从而增加了代码的可变性和可选择性。接口可以提高代码的测试性和可测性因为它可以方便地使用模拟对象或桩对象来替代真实对象从而简化了单元测试和集成测试。 二、空接口 interface{} Go语言中的接口是一种类型它定义了一组方法的集合接口可以分为空接口和非空接口。空接口(interface{})是一种特殊的接口类型它没有任何方法因此可以表示任何类型的值。非空接口则是指至少有一个方法的接口类型。 Jordan Oreilli 对空接口的一个很好的定义 接口是两件事物它是一组方法但它也是一种类型。 空接口 interface{} 类型是没有方法的接口。由于 Go 语言没有 implements 关键字所有类型都至少实现零个方法并且接口是隐式实现的所有类型都满足空接口。 1、eface的定义 在 Go 的泛型未敲定前空接口和断言广泛用于实现泛型空接口的底层数据结构是 eface它是一个结构体包含两个字段_type和data。 eface结构体定义如下 type eface struct {_type *_typedata unsafe.Pointer }其中_type是一个指向类型信息的指针它包含了类型的名称、大小、对齐方式等信息。不了解的请看上一节篇《Go基础篇类型系统》data是一个指向实际值的指针它可以存储任何类型的值。 举个简单的例子 type MyString string// 输出val的值和类型这里只是稍微用到了反射reflect的TypeOf方法获取类型后面我会详细讲的 func Print(val interface{}) {fmt.Println(val, reflect.TypeOf(val)) }func TestPrint(t *testing.T) {name : linzy1Print(name)var Myname MyString linzy2Print(Myname) }例子中在空接口被赋值string类型和自定义类型时的值虽然相同但是类型却不同且都不是空接口 interface{} 类型。这是为什么呢 当我们使用空接口来存储一个值时Go语言会将该值的类型信息和实际值分别存储在eface结构体的_type和data字段中。在需要使用该值时Go语言会根据_type字段中的类型信息将data字段中的值转换为相应的类型并进行相应的操作。 具体来说当一个空接口变量被赋值为string类型的值时Go语言会将该值的类型描述信息存储在该变量的_type字段中。这个类型描述信息包含了string类型的名称、大小、对齐方式等信息可以通过反射包中的TypeOf()函数获取。 需要注意的是由于空接口可以存储任何类型的值因此在使用空接口时需要进行类型断言或类型转换以确保程序的正确性。 2、需要注意的问题 空接口可以存储任何类型的值但是 []interface{} 空接口切片类型不一样[]interface{} 可以存储任何类型的值但是不能直接赋值切片或者切片转换。 举个简单的例子 func PrintAll(vals []interface{}) {fmt.Println(vals Type is:, reflect.TypeOf(vals))for _, val : range vals {fmt.Println(val, reflect.TypeOf(val))} }func TestPrint(t *testing.T) {names : []string{stanley, david, oscar}// ./interface_test.go:144:11: cannot use names (variable of type []string) as type []interface{} in argument to PrintAll// PrintAll(names)ns : make([]interface{}, len(names))for i, name : range names {ns[i] name}PrintAll(ns)ns []interface{}{linzy, 32, 1.68}PrintAll(ns) }在Go语言中[]interface{}和[]string是两种不同的类型它们之间不能直接赋值或转换。虽然[]interface{}可以存储任何类型的值包括string类型但是它本身并不是string类型的切片因此不能直接赋值给[]string类型的变量。 最核心的点在于 slicetype 中的 elem 类型描述不同所以他们是两种不同的类型。 type slicetype struct {typ _typeelem *_type }三、非空接口 非空接口是指具有实际类型的接口想要赋值给非空接口类型必须要实现该接口的所有方法也就是说它不是空接口。 1、iface的定义 在Go语言中非空接口的底层数据结构是iface它是一个结构体定义如下 type iface struct {tab *itabdata unsafe.Pointer }其中tab是一个指向方法表的指针data是一个指向实际对象的指针。 2、itab的定义 itab是一个结构体它定义了接口类型和实现类型之间的关系包括接口类型的方法集合、实现类型的方法集合和方法表等信息。itab的定义如下 type itab struct {inter *interfacetype_type *_typehash uint32_ [4]bytefun [1]uintptr }其中inter是一个指向接口类型的指针_type是一个指向动态类型的指针hash是实现类型的哈希值fun是一个指向方法表的指针数组指向的是动态类型实现接口方法的地址。 interfacetype和_type都是类型对象它们包含了类型的名称、大小、对齐方式、方法集合等信息。uintptr是一个无符号整数类型它可以存储指针类型的值。 itab结构体的大小是可变的因为它的最后一个字段fun是一个指针数组它的长度取决于实现类型的方法集合的大小。当实现类型的方法集合发生变化时Go语言会重新生成一个新的itab结构体并将其添加到缓存中以便后续可以复用。 举个简单的例子 func TestReadWriter(t *testing.T) {// 定义io.ReadWriter接口类型的变量rw需要实现Read和Write两个方法var rw io.ReadWriterf, _ : os.Open(linzy.txt)defer f.Close()rw f// os.Stat函数获取文件的大小Stat, _ : f.Stat()tmp : make([]byte, Stat.Size())rw.Read(tmp)fmt.Println(string(tmp)) }赋值的变化过程 当你将f \*os.File类型变量赋值给rw变量时Go语言会生成一个新的itab结构体。它的inter字段指向io.ReadWriter接口类型的描述信息_type字段指向*os.File类型的描述信息fun字段指向一个方法表其中包含了io.ReadWriter接口类型的需要的所有方法拷贝的是方法地址。Go语言会使用一个全局的哈希表来缓存itab结构体这个itab结构体会被缓存起来以便后续可以复用。当你调用rw.Read(tmp)方法时Go语言会根据rw变量对应的itab指针找到对应的方法表并调用其中的Read方法。 总结 当你将一个实现了接口类型的值赋给接口类型的变量时Go语言会根据实际对象的类型和接口类型的方法集合生成一个新的itab结构体并将其赋值给接口类型变量对应的itab指针。 这个itab结构体包含了接口类型的方法集合、实现类型的方法集合和方法表等信息通过这些信息可以实现接口方法的调用。 3、itab缓存 一个非空接口类型和一个动态类型就可以确定一个itab的内容容易出现重复的itab结构体。Go为了避免重复生成itab结构体的开销并且可以减少内存的使用提高程序的性能。 Go语言会使用一个全局的哈希表来缓存itab结构体这个哈希表的键是一个由接口类型, 动态类型组成的key值是对应的*itab结构体的指针。当我们创建一个非空接口变量时Go语言会先在缓存中查找对应的itab结构体如果找到了就直接使用否则就动态生成一个新的itab结构体并将其添加到缓存中以便后续可以复用。 但是这里说的哈希表跟go的map哈希表不相同itab设计的哈希表结构更简单 type itabTableType struct {size uintptr // length of entries array. Always a power of 2.count uintptr // current number of filled entries.entries [itabInitSize]*itab // really [size] large }需要一个itab时会首先去itabTable里查找计算哈希值时会用到接口类型(itab.inter)和动态类型(itab._type)的类型 func itabHashFunc(inter *interfacetype, typ *_type) uintptr {// compiler has provided some good hash codes for us.return uintptr(inter.typ.hash ^ typ.hash) }如果能查询到对应的itab指针就直接拿来使用。若没有就要再创建然后添加到itabTable中。
http://www.hkea.cn/news/14416369/

相关文章:

  • 站酷设计网站官网入口下载广州市公司网站建设价格
  • 十大免费模板网站深圳网络seo推广
  • 做签证宾馆订单用啥网站石家庄电子商务网站建设
  • 网站所有权规模以上工业企业名单
  • 营销型网站建设测验题参考消息官网手机网
  • 自己建设购物网站手工制作教程
  • 58网站建设58xiamen做豆制品的网站
  • 施工程找工程做哪个网站好jsp网站开发技巧
  • 网站建设优化服务器哪里有免费建设网站
  • 响应式网站和展示式区别网络广告案例以及分析
  • iis7.5发布网站南昌网站建设哪家最好
  • 网站建设的知识点有哪些网站模板红黑
  • 专门做销售培训的网站互联网创业平台
  • 阳泉网站开发本地搭建 wordpress
  • 网站开发 模块化linux软件开发工具
  • 太月星网站建设程序开发网页设计厦门建设官网
  • 网站建设方案汇报中国企业网站设计案例
  • 网站开发安全问题wordpress网易云插件
  • 郑州百度网站推广企业联系电话
  • 网站制作切片长沙哪里做网站
  • 晋江建设局网站wordpress后台用户名
  • 国内响应式网站案例vue网站开发实例
  • 瘦身网站开发目的中国建设教育协会网站证书
  • 技术难度高的网站开发网页设计模板html代码五四主题
  • 网站建设备案流程安卓手机优化大师官方下载
  • 快递网站怎么制作常州网站建设推广
  • 嘉兴网站建设哪家做得好高端网站设计哪家好
  • 实用网站建设期末考试商丘高端网站建设
  • 长沙市做网站公司徐州关键词优化平台
  • 个人电脑安装win2003做网站河北石家庄天气