博客
关于我
《go in action》第5章(Go语言的类型系统)读书笔记
阅读量:680 次
发布时间:2019-03-17

本文共 3011 字,大约阅读时间需要 10 分钟。

5.1 用户定义的类型

不使用字段名创建结构类型的值,这咱形式下值的顺序很重要。

type user struct {	name  string	age   int	email string}lisa := user{"Lisa", 20, "lisa@email.com"}

两种不同类型的值即便相互兼容,也不能互相赋值。编译器不会对不同类型的值做隐式转换。

type Duration int64func main() {   	var dur Duration	dur = int64(100)}

上述代码会产生编译错误,int64的值不能做为类型Duration的值来用。

5.2 方法

如果一个函数的接收者,这个函数就被称为方法。

Go语言里有两种类型的接收者: 值接收者和指针接收者。

值接收者使用值的副本来调用方法,指针接收者使用实际值来调用方法。

5.3 类型的本质

5.3.1 内置类型

内置类型是由语言提供的一组类型。分别是数值类型,字符类型和布尔类型。这些类型本质上是原始的类型。因此,当对这些值进行增加或者删除的时候,会创建一个新值。

5.3.2 引用类型

Go语言里的引用类型有如下几个:切片、映射、通道、接口和函数类型。当上声明述类型的变量时,创建的变量被称作标头值。每个引用类型创建的标头值是包含一个指向底层数据结构的指针。每个引用类型还包含一组独特的字段,用于管理底层数据结构。因为标头值是为复制而设计的,所以永远不需要共享一个引用类型的值。标头值里包含一个指针,因此通过复制来传递一个引用类型的值的副本,本质上就是在共享底层数据结构。

5.3.3 结构类型

是使用值接收者还是指针接收者,不应该由该方法是否修改了接收到的值来决定。这个决策应该基于类型的本质。(原始类型,使用值接收者。非原始类型使用指针接收者。)这条规则的一个例外是,需要让类型值符合某个掊的时候,即便类型的本质是非原始的,也可以选择使用值接收者声明方法。

5.4 接口

5.4.2 实现

接口是用来定义行为的类型。这些被定义的行为不由接口直接实现,而是通过方法由用户定义的类型实现。

用户定义的类型可以实现任何接口,所以对接口值方法的调用自然就是一种多态。在这个关系里,用户定义的类型通常叫作实体类型。

接口值是一个两个字长度的数据结构,第一个字包含一个指向内部表的指针。这个内部表叫作iTable,包含了所存储的值的类型值信息。iTable包含了已存储的值的类型信息以及与这个值相关联的一组方法。第二个字是一个指向所存储值的指针。将类型信息和指针组合在一起,就将这两个值组成了一种特殊的关系。

type notifier interface {   	notify()}type user struct {   	name  string	email string}// notify implements a method with a pointer receiver.func (u *user) notify() {   	fmt.Printf("Sending user email to %s<%s>\n",		u.name,		u.email)}

下图展示了在user类型赋值后接口变量的值的内部布局

image

下图展示了一个指针赋值给接口之后发生的变化。

image

5.4.3 方法集

方法集定义了接口的接受规则。

方法集定义了一组关联到给定类型的值或者指针的方法。定义方法时使用的接收者的类型决定了这个方法是关联到值,还是关联到指针,还是两个都关联。

从接收者类型的角度来看方法集

Methods Rceivers Values
(t T) T and *T
(t *T) *T

上面的规则是说,如果使用指针接收者来实现一个接口,那么只有指向那个类型的指针才能够实现对应的接口。如果使用值接收者来实现一个接口,那么那个类型的值和指针都能够实现对应的接口。之所以有这种限制是因为编译器并不是总能自动获得一个值的地址。

// main is the entry point for the application.func main() {	// Create a value of type User and send a notification.	u := user{"Bill", "bill@email.com"}	sendNotification(u)	// ./listing36.go:32: cannot use u (type user) as type	//                     notifier in argument to sendNotification:	//   user does not implement notifier	//                          (notify method has pointer receiver)}func sendNotification(n notifier) {	n.notify()}

将上述代码做如下改动,不再报错:

func main() {	u := user{"Bill", "bill@email.com"}	sendNotification(&u)}

再看下面的例子

image

  • 23,27行都会输出demoName
  • 30行正确
  • 31行报错。因为setName方法的接收者是指针类型,所以编译器认为p2并没有实现setName方法。

5.5 嵌入类型

可以直接通过外部类型的值来访问内部类型的标识符。

内部类型实现的接口会自动提升到外部类型。

如果外部类型实现与内部类型同样的方法,则内部类型的实现就不会被提升。不过内部类型的值会一直存在,可以通过直接访问内部类型的值,来调用没有被提升的内部类型实现的方法。

type user struct {	name  string	email string}func (u *user) notify() {	fmt.Printf("Send user email to %s<%s>\n", u.name, u.email)}type admin struct {	user	level string}func (a *admin) notify() {	fmt.Printf("Send admin email to %s<%s>\n", a.name, a.email)}func main() {	ad := admin{		user: user{			name:  "ball",			email: "ball@email.com",		},		level: "super",	}    //内部类型的方法没有被提升	ad.notify()	//调用内部类型的方法	ad.user.notify()}

5.6 公开或未公开的标识符

好的实践是使用与代码所在文件夹一样的名字作为包名。

当一个标识符的名字以小写字母开头时,这个标识符就是未公开的,即包外的代码不可见。

将工厂函数命名为New是Go语言的一个习惯。

即便内部类型是未公开的,内部类型里声明的字段依旧可以是公开的。当内部类型提升到了外部类型,这些公开的字段就可以通过外部类型的字段值来访问。

转载地址:http://mcwhz.baihongyu.com/

你可能感兴趣的文章
NIFI大数据进阶_Json内容转换为Hive支持的文本格式_操作方法说明_01_EvaluteJsonPath处理器---大数据之Nifi工作笔记0031
查看>>
NIFI大数据进阶_Kafka使用相关说明_实际操作Kafka消费者处理器_来消费kafka数据---大数据之Nifi工作笔记0037
查看>>
NIFI大数据进阶_Kafka使用相关说明_实际操作Kafka生产者---大数据之Nifi工作笔记0036
查看>>
NIFI大数据进阶_NIFI的模板和组的使用-介绍和实际操作_创建组_嵌套组_模板创建下载_导入---大数据之Nifi工作笔记0022
查看>>
NIFI大数据进阶_NIFI监控功能实际操作_Summary查看系统和处理器运行情况_viewDataProvenance查看_---大数据之Nifi工作笔记0026
查看>>
NIFI大数据进阶_NIFI监控的强大功能介绍_处理器面板_进程组面板_summary监控_data_provenance事件源---大数据之Nifi工作笔记0025
查看>>
NIFI大数据进阶_NIFI集群知识点_认识NIFI集群以及集群的组成部分---大数据之Nifi工作笔记0014
查看>>
NIFI大数据进阶_NIFI集群知识点_集群的断开_重连_退役_卸载_总结---大数据之Nifi工作笔记0018
查看>>
NIFI大数据进阶_使用NIFI表达式语言_来获取自定义属性中的数据_NIFI表达式使用体验---大数据之Nifi工作笔记0024
查看>>
NIFI大数据进阶_内嵌ZK模式集群1_搭建过程说明---大数据之Nifi工作笔记0015
查看>>
NIFI大数据进阶_内嵌ZK模式集群2_实际操作搭建NIFI内嵌模式集群---大数据之Nifi工作笔记0016
查看>>
NIFI大数据进阶_外部ZK模式集群1_实际操作搭建NIFI外部ZK模式集群---大数据之Nifi工作笔记0017
查看>>
NIFI大数据进阶_实时同步MySql的数据到Hive中去_可增量同步_实时监控MySql数据库变化_操作方法说明_01---大数据之Nifi工作笔记0033
查看>>
NIFI大数据进阶_实时同步MySql的数据到Hive中去_可增量同步_实时监控MySql数据库变化_操作方法说明_02---大数据之Nifi工作笔记0034
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_01_实际操作---大数据之Nifi工作笔记0029
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_说明操作步骤---大数据之Nifi工作笔记0028
查看>>
NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
查看>>
NIFI数据库同步_多表_特定表同时同步_实际操作_MySqlToMysql_可推广到其他数据库_Postgresql_Hbase_SqlServer等----大数据之Nifi工作笔记0053
查看>>
NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南001---大数据之Nifi工作笔记0068
查看>>