结构体类型可以包含若干字段,每个字段通常都需要有确切的名字和类型。也可以不包含任何字段,这样并不是没有意义的,因为还可以为这些类型关联上一些方法,这里可以把方法看作事函数的特殊版本。

  函数事独立的程序实体,可以声明有名字的函数,也可以声明没名字的函数,还可以把它们当作普通的值传来传去(把具有相同签名的函数抽象陈独立的函数类型,作为一组输入或输出的代表)。方法则不同,它需要名字,不能被当作值来看待,更重要的是,它必须隶属于某一个类型。方法所属的类型会通过期声明中的接收者声明(关键字func和方法名称之间那个圆括号包裹起来的内容,其中必须包含确切的名称和类型字面量,这个接收者的类型其实就是当前方法所属的那个类型,而接收者的名称则用于在当前方法中引用它所属的类型的当前值)体现出来。

type AnimalCategory struct {kingdom string // 界。phylum  string // 门。class   string // 纲。order   string // 目。family  string // 科。genus   string // 属。species string // 种。
}func (ac AnimalCategory) String() string {return fmt.Sprintf("%s%s%s%s%s%s%s",ac.kingdom, ac.phylum, ac.class, ac.order,ac.family, ac.genus, ac.species)
}

  从String方法的接收者声明可以看出,它隶属于AnimalCategory类型。通过该方法的接收者名称ac,可以在其中引用到当前的任何一个字段或者调用到当前值的任何一个方法(包括string方法自己)。使用时可以这样表示

    category := AnimalCategory{species: "cat"}fmt.Printf("The animal category: %s\n", category)

  在Go语言中,可以通过为一个类型编写名为String的方法,来自定义该类型的字符串表示形式,这个String方法不需要任何参数声明,但需要一个string类型的结果声明。正因为如此,在调用fmt.Print函数时,无需显式调用它的string方法,fmt.Print会自己去寻找它。

  方法隶属的类型并不局限于结构图,但必须时某个自定义的数据类型,并且不能时任何接口类型。一个数据类型关联的所有方法,共同组成了该类型的方法集合。同一个方法集合中的方法不能出现重名,并且如果它们所属的是一个结构图类型,那么它们的名称与该类型中任何字段的名称也不能重复。

  可以把结构体类型中的一个字段看作是它的一个属性或一项数据,再把隶属于它的一个方法看作是附加再其中数据之上的一个能力或一项操作。将属性及其能力封装再一起,是面向对象编程的一个主要原则。

1、结构体嵌入字段

  Go语言规范规定,如果一个字段的声明中只有字段的类型名而没有字段的名称,那么它就是一个嵌入字段。可以通过此类型变量的名称后跟“.”,再后跟嵌入字段类型的方法引用到该字段。

type Animal struct {scientificName string // 学名。AnimalCategory        // 动物基本分类。
}func (a Animal) Category() string {return a.AnimalCategory.String()
}

  Category方法的接收者类型是Animal,接收者名称是a。在该方法中,通过表达式a.AnimalCategory选择到了a这个嵌入字段,然后又选择了该字段的String方法并调用了它。

  把一个结构体类型嵌入到另一个结构体中的,嵌入字段的方法集合会被无条件地合并进被嵌入类型地方法集合中。

    animal := Animal{scientificName: "American Shorthair",AnimalCategory: category,}fmt.Printf("The animal: %s\n", animal)

  这里声明了Animal类型地变量animal并对它进行初始化,把字符串值“American Shorthair”赋值给它的字段scientificName,并把前面声明过的变量category赋给它的嵌入字段AnimalCategory

  那再后面使用fmt.Printf函数相当于调用animal的String方法(虽然还没有为Animal类型编写String方法,但这样做并没有问题,因为嵌入字段AnimalCategory的String方法会被当做animal的方法调用)

  那如果为Animal类型也编写一个String方法呢?会调用哪一个?

  答案是animal的String方法会被调用,AnimalCategory的String方法被屏蔽掉了。注意:只要名称相同,无论这两个方法的签名是否一致,被嵌入类型的方法都会屏蔽掉嵌入字段的同名方法。

  同样,如果两个结构体类型中存在同名的字段,那嵌入字段中的那个字段一定会被“屏蔽‘。即使是两个同名的成员,一个是字段,一个是方法,这种屏蔽现象依然会存在。

  不过,即使被屏蔽了仍然可以通过链式的选择表达式,选择到嵌入字段的字段或方法。

  当出现多层嵌入时,屏蔽现象会以嵌入的层级为依据,嵌入层级越深的字段或方法越可能被屏蔽。如果同一层级的多个嵌入字段拥有同名的字段或方法,那么被嵌入类型的值那里,选择此名称的时候就会引发一个编译错误。

2、Go语言用嵌入字段实现了继承吗?

  Go语言中根本没有继承的概念

  它所做的事通过嵌入字段的方式实现了类型之间的组合。

  面向对象编程中的继承事通过牺牲一定的代码简洁性来换取可扩展性,这种可扩展性事通过侵入的方式实现的。

  而类型之间的组合采用的是非声明的方式。不需要显式声明,而且也非侵入式的。只是通过嵌入字段的方式把一个类型的属性和能力嫁接给另外一个类型

3、值方法和指针方法都是什么意思?有什么区别

  方法的接收者必须是某个自定义的数据类型,而且不能是接口类型或接口的指针类型。

  值方法就是接收者是非指针的自定义数据类型的方法。前面的AnimalCategory、Animal声明的那些方法都是值方法。

type Cat struct {name stringAnimal
}func (cat *Cat) SetName(name string) {cat.name = name
}

  方法SetName的接收者类型是*Cat(Cat类型的指针类型)。那指针方法,就是接收者类型是指针类型的方法

  区别:

    1)值方法的接收者是该方法所属的那个类型值的一个副本,在该方法内对该副本的修改一般不不会体现在原值上(除非这个类型本身是某个引用类型(如切片或字典)的别名类型)。

      指针方法的接收者,是该方法所属那个基本类型值的指针值的一个副本,这样的方法内对该副本指向值的进行修改,一定会体现在原值上。

    (2)一个自定义数据类型的方法集合中仅会包含它的所有值方法

      而该类型的指针类型的方法集合却包含了所有值方法和所有指针方法

转载于:https://www.cnblogs.com/yuxiaoba/p/9656269.html

[Go]结构体及其方法相关推荐

  1. 005 GO-高级数据类型(结构体和方法)

    005 GO-高级数据类型(结构体和方法) http://note.youdao.com/noteshare?id=864cc29d2ca6082949d875280f3f5448&sub=D ...

  2. 【Go】Go基础(八):结构体和方法

    一. 结构体(struct) 1.结构体定义 type identifier struct {field1 type1field2 type2... } 声明:new(Type) 和 &Typ ...

  3. C读取配置文件,然后写入结构体的方法

    方法一: #include<stdio.h> #include<stdlib.h> #include<string.h>#define MAX 4096 #defi ...

  4. Rust中对某个结构体实现方法于rust中的关联函数

    写法比较独特,但与go语言相差不了太多,都是为结构体单独进行方法的实现: struct Rectangle{width: u32,length:u32, } impl Rectangle{fn are ...

  5. 结构体+sort方法

    昨天做了一道简单但很麻烦的题,我只能想到结构体,并用了STL的sort方法解决了它.不过从中有许多细节问题. 题目: Problem Description Lcy wanted to choose ...

  6. go在方法中修改结构体的值_[Go]结构体及其方法

    结构体类型可以包含若干字段,每个字段通常都需要有确切的名字和类型.也可以不包含任何字段,这样并不是没有意义的,因为还可以为这些类型关联上一些方法,这里可以把方法看作事函数的特殊版本. 函数事独立的程序 ...

  7. 总结几种结构体初始化方法 (转)

    结构体能自由组装数据,是一种很常见的数据打包方法.当我们定义一个结构体后,没有初始化就使用,就会使用到垃圾数据,而且这种错误很难发现.对于定义的任何变量,我们最好都先初始化. 除了使用memset和Z ...

  8. C语言骚操作:结构体初始化方法

    首先定义俩结构体: typedef struct {int a0;int b0; }S0;typedef struct {int a1;int b1;S0 s0; }S1; 首先想到的初始化方法是: ...

  9. C++结构体初始化方法

    在 C++ 里可以将结构体看作没有任何成员函数的对象,下面对 C++ 结构体的几种初始化方法进行总结. 文章目录 直接赋值 利用函数赋值 构造函数初始化 直接赋值 #include <bits/ ...

最新文章

  1. java模拟验证码生成
  2. 在Java程序设计中,设置环境变量path和classpath的作用分别是什么?
  3. 程序员正在消失!90%的人都不知道,写不出好代码,是输在了这点上!
  4. Android Studio 小技巧/快捷键 合集
  5. 悲观锁和乐观锁和gap锁
  6. package.json mysql_package.json入门
  7. python贪吃蛇小游戏_python开发贪吃蛇小游戏
  8. King Gym - 102471H
  9. shiro学习(15):使用注解实现权限认证和后台管理
  10. IE8“开发人员工具”(下)
  11. 信息学奥赛一本通(1122:计算鞍点)
  12. java stream 取不同的数据_基础篇:JAVA.Stream函数,优雅的数据流操作
  13. 二维haar小波matlab_MATLAB实验之二维小波变换[附效果图]
  14. Python 日期时间处理
  15. 520送什么礼物好呢、适合送女友的礼物推荐
  16. 解决WPS表格图片打印拉伸问题
  17. java实现爬虫,爬取网易歌单信息
  18. win10系统双屏如何设置不同的桌面
  19. 突然的:图形设备驱动程序错误代码 43 -(已解决)
  20. 杭电计算机学院2019年奖学金,关于计算机学院2019-2020学年国家励志奖学金评选的通知...

热门文章

  1. UBOOT启动内核过程
  2. px,em,rem,vh,vw,vmin,vmax的区别
  3. lvs调整hash表大小
  4. winsock2之最简单的win socket编程
  5. 操作无法完成.键入的打印机名不正确,或者指定的打印机没有连接到服务器上.有关详细信息,请单帮助...
  6. 0x00000000指令引用的内存不能为written_jvm的内存结构
  7. 票房破五十亿!用Python分析李焕英为啥能逆袭《唐探3》
  8. html从入门到精通前锋,街篮新手攻略 从入门到精通的心得分享二
  9. 目录忽略_宣传册设计中目录的构思方法和运用
  10. 让word不显示计算机名作者,如何使word在其他电脑上也不显示回车符