go语言中的大多数类型都是值予以,并且都可以包含对应的操作方法,在需要的时候你可以给任意类型增加新方法。二在实现某个接口时,无需从该接口集成,只需要实现该接口要求的所有方法即可。任何类型都可以被any类型引用。any类型是空接口 interface{}

Go语言中,你可以给任意类型(包括内置类型,但不包括指针类型)添加相应的方法  .如下
    1. package main

    2. import (

    3. "fmt"

    4. )

    5. func main() {

    6.     person.Go2School()

    7. }

    8. func (ps Person) Go2School() {

    9.     fmt.Println("go to school")

    10. }

    11.  

Go语言中的大多数类型都基于值语义,包括:
  1.     基本类型,如byte、int、bool、float32、float64和string等;
  2.     复合类型,如数组(array)、结构体(struct)和指针(pointer)等。
 
值语义和引用语义                                                                                               
  1. a := 10

  2. b := a

  3. b = b + 1

  4. fmt.Println(b)

  5. fmt.Println(a)

  6. 输出:11,10

  7. c := 10

  8. d := &c

  9. *d += 1

  10. fmt.Println(c)

  11. fmt.Println(*d)

  12. 输出:11,11

Go语言中有4个类型比较特别,看起来像引用类型
        数组切片:指向数组(array)的一个区间。
        map:极其常见的数据结构,提供键值查询能力。
        channel:执行体(goroutine)间的通信设施。
        接口(interface):对一组满足某个契约的类型的抽象


结构体                                                                                                        
    1. 定义:

    2. type Rect struct {

    3.     x, y float64

    4.     width, height float64

    5. }

    6. 初始化

    7. rect1 := new(Rect)

    8. rect2 := &Rect{}

    9. rect3 := &Rect{0, 0, 100, 200}

    10. rect4 := &Rect{width: 100, height: 200}

    构造函数                                                                                                                                                                                                          
Go语言中,未进行显式初始化的变量都会被初始化为该类型的零值,例如bool类型的零值为false,int类型的零值为0,string类型的零值为空字符串。
Go语言中没有构造函数的概念,对象的创建通常交由一个全局的创建函数来完成,以NewXXX来命名,表示“构造函数”:
  1. package main

  2. //person类

  3. type Person struct {

  4.     Name string

  5.     Age int

  6.     Sex string

  7. }

  8. //person构造函数

  9. func NewPerson(name string, sex string, age int) *Person {

  10.     return &Person{Name: name, Sex: sex, Age: age}

  11. }

  12. //person类ResetName1方法 (传值)

  13. func (ps Person) ResetName1(name string) {

  14.     ps.Name = name

  15. }

  16. //person类ResetName1方法 (传址)

  17. func (ps *Person) ResetName2(name string) {

  18.     ps.Name = name

  19. }

  20. //student类

  21. type Student struct {

  22.     Class string

  23.     Grade string

  24.     *Person

  25. }

  26. //student构造函数

  27. func NewStudent(name string, sex string, age int, class string, grade string) *Student {

  28.     return &Student{Person: NewPerson(name, sex, age), Class: class, Grade: grade}

  29. }

 
 
匿名组合:类的继承是使用了匿名组合的方式                                                                         
    1. package main

    2. type Person struct {

    3.     Name string

    4.     Age int

    5.     Sex string

    6. }

    7. //构造函数

    8. func NewPerson(name string, sex string, age int) *Person {

    9.     return &Person{Name: name, Sex: sex, Age: age}

    10. }

    11. func (ps Person) ResetName1(name string) {

    12.     ps.Name = name

    13. }

    14. func (ps *Person) ResetName2(name string) {

    15.     ps.Name = name

    16. }

    17. //继承自Person

    18. type Student struct {

    19.     Class string

    20.     Grade string

    21.     Person //或者*Person

    22. }

    23. 这样Student就继承自了 Person类

     
可见性                                                                                                         
  1. 要使某个符号对其他包(package)可见(即可以访问),需要将该符号定义为以大写字母开头

    1. type Rect struct {

    2.     X, Y float64

    3.     Width, Height float64

    4. }

  2. 这样,Rect类型的成员变量就全部被导出了,可以被所有其他引用了Rect所在包的代码访问到。

    1. func (r *Rect) area() float64 {

      1. return r.Width * r.Height

  3. 这样,Rect的area()方法只能在该类型所在的包内使用。

  4. Go语言中符号的可访问性是包一级的而不是类型一级的

 
接口                                                                                                                                                                                                             
  1. 入侵接口
          c#和Java中的接口时入侵是接口
  2. 非入侵接口
       go的接口是非入侵式接口
Go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口
type File struct {
// ...
}
func (f *File) Read(buf []byte) (n int, err error)
func (f *File) Write(buf []byte) (n int, err error)
func (f *File) Seek(off int64, whence int) (pos int64, err error)
func (f *File) Close() error
这里我们定义了一个File类,并实现有Read()Write()Seek()Close()等方法。设想我们有如下接口:
type IFile interface {
Read(buf []byte) (n int, err error)
Write(buf []byte) (n int, err error)
Seek(off int64, whence int) (pos int64, err error)
Close() error
}
type IReader interface {
    Read(buf []byte) (n int, err error)
}
type IWriter interface {
    Write(buf []byte) (n int, err error)
}
type ICloser interface {
    Close() error
}
尽管File类并没有从这些接口继承,甚至可以不知道这些接口的存在,但是File类实现了这些接口,可以进行赋值:
var file1 IFile = new(File)
var file2 IReader = new(File)
var file3 IWriter = new(File)
var file4 ICloser = new(File)  
Go语言的非侵入式接口,看似只是做了很小的文法调整,实则影响深远。
其一,Go语言的标准库,再也不需要绘制类库的继承树图。你一定见过不少C++、Java、C#类库的继承树图。在Go中,类的继承树并无意义,你只需要知道这个类实现了哪些方法,每个方法是啥含义就足够了。
其二,实现类的时候,只需要关心自己应该提供哪些方法,不用再纠结接口需要拆得多细才合理。接口由使用方按需定义,而不用事前规划。
其三,不用为了实现一个接口而导入一个包,因为多引用一个外部的包,就意味着更多的耦合。接口由使用方按自身需求来定义,使用方无需关心是否有其他模块定义过类似的接口  
 
 
接口赋值                                                                                                                                                                                                             
接口赋值在Go语言中分为如下两种情况:
  1.  将对象实例赋值给接口;
  2.  将接口实例赋值给接口;
  1. //对象赋值给接口

    1. var interfaces IStudent = NewStudent("Jessica", "male", 18, "class1", "grade1")

    2. interfaces.Go2School()

Go语言中,只要两个接口拥有相同的方法列表(次序不同不要紧),那么它们就是等同的,可以相互赋值  
    1. package one

    2. type ReadWriter interface {

    3.     Read(buf []byte) (n int, err error)

    4.     Write(buf []byte) (n int, err error)

    5. }

    6. package two

    7. type IStream interface {

    8. Write(buf []byte) (n int, err error)

    9. Read(buf []byte) (n int, err error)

    10. }

     
这里我们定义了两个接口,一个叫one.ReadWriter,一个叫two.Istream,两者都定义了Read()、Write()方法,只是定义次序相反。one.ReadWriter先定义了Read()再定义了Write(),而two.IStream反之。
Go语言中,这两个接口实际上并无区别,因为:
  1.           任何实现了one.ReadWriter接口的类,均实现了two.IStream;
  2. 任何one.ReadWriter接口对象可赋值给two.IStream,反之亦然;
  3. 在任何地方使用one.ReadWriter接口与使用two.IStream并无差异。
以下这些代码可编译通过:
    1. var file1 two.IStream = new(File)

    2. var file2 one.ReadWriter = file1

    3. var file3 two.IStream = file2

接口赋值并不要求两个接口必须等价。如果接口A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A。例如,假设我们有Writer接口:
type Writer interface {
          Write(buf []byte) (n int, err error)
}
就可以将上面的one.ReadWriter和two.IStream接口的实例赋值给Writer接口:
var file1 two.IStream = new(File)
var file4 Writer = file1
 
接口查询                                                                                                                                                                                                            
          switch进行接口查询
    1. // OOPTest project main.go

    2. package main

    3. type IStudent interface {

    4.     Go2School()

    5. }

    6. type IPerson interface {

    7.     Speak(word string)

    8.     Eat(food string)

    9. }

    10. func main() {

    11. //std := NewStudent("Jessica", "male", 18, "class1", "grade1")

    12. //psn := NewPerson("James", "female", 20)

    13. //语句switch中的value必须是接口类型,变量str的类型为转换后的类型。/

    14. var IStd interface{} = NewStudent("Jessica", "male", 18, "class1", "grade1")

    15. switch per := IStd.(type) {

    16.     case IStudent:

    17.         per.Go2School()

    18.     case IPerson:

    19.         per.Eat("pig")

    20. }

    21. }

     
类型断言
    1. // OOPTest project main.go

    2. package main

    3. type IStudent interface {

    4.     Go2School()

    5. }

    6. type IPerson interface {

    7.     Speak(word string)

    8.     Eat(food string)

    9. }

    10. func main() {

    11. //std := NewStudent("Jessica", "male", 18, "class1", "grade1")

    12. //psn := NewPerson("James", "female", 20)

    13. //语句switch中的value必须是接口类型,变量str的类型为转换后的类型。

    14. var IStd interface{} = NewStudent("Jessica", "male", 18, "class1", "grade1")

    15. //switch per := IStd.(type) {

    16. //case IStudent:

    17. // per.Go2School()

    18. //case IPerson:

    19. // per.Eat("pig")

    20. //}

    21. //上面的转换有一个问题,如果该值不包含一个字符串,则程序会产生一个运行时错误。为了避免这个问题,可以使用“comma, ok”的习惯用法来安全地测试值是否为一个字符串:

    22. if types, ok := IStd.(IStudent); ok {

    23.     types.Go2School()

    24. } else if types, ok := IStd.(IPerson); ok {

    25.     types.Eat("pig")

    26. }

    27. }

接口组合:接口的继承                                                                                                                                                                                               

  1. type IStudentinterface{
  2. Go2School()
  3. }
  4. type IPersoninterface{
  5. Speak(word string)
  6. Eat(food string)
  7. }
  8. type Animalinterface{
  9. IPerson
  10. IStudent
  11. }
Any类型                                                                                                                                                                                                                      
由于Go语言中任何对象实例都满足空接口interface{},所以interface{}看起来像是可
以指向任何对象的Any类型,如下:
  1. var v1 interface{}=1// 将int类型赋值给interface{}
  2. var v2 interface{}="abc"// 将string类型赋值给interface{}
  3. var v3 interface{}=&v2 // 将*interface{}类型赋值给interface{}
  4. var v4 interface{}=struct{ X int}{1}
  5. var v5 interface{}=&struct{ X int}{1}
当函数可以接受任意的对象实例时,我们会将其声明为interface{},最典型的例子是标
准库fmt中PrintXXX系列的函数,例如:
  1. func Printf(fmt string, args ...interface{})
  2. func Println(args ...interface{})
总体来说,interface{}类似于COM中的IUnknown,我们刚开始对其一无所知,但可以通

过接口查询和类型查询逐步了解它。

Go面向对象(三)的更多相关文章

  1. Python面向对象三要素-继承(Inheritance)

    Python面向对象三要素-继承(Inheritance) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.继承概述 1>.基本概念 前面我们学习了Python的面向对象三 ...

  2. Python面向对象三要素-封装(Encapsulation)

    Python面向对象三要素-封装(Encapsulation) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.封装概述 将数据和操作组织到类中,即属性和方法 将数据隐藏起来,给 ...

  3. JavaScript 面向对象(三) —— 高级篇

    JavaScript 面向对象(一) —— 基础篇 JavaScript 面向对象(二) —— 案例篇 一.json方式的面向对象 首先要知道,js中出现的东西都能够放到json中.关于json数据格 ...

  4. JavaScript面向对象(三)——继承与闭包、JS实现继承的三种方式

      前  言 JRedu 在之前的两篇博客中,我们详细探讨了JavaScript OOP中的各种知识点(JS OOP基础与JS 中This指向详解 . 成员属性.静态属性.原型属性与JS原型链).今天 ...

  5. Python之面向对象三

    面向对象的三大特性: 多态 多态指的是一类事物有多种形态.Python3天生支持多态. 动物有多种形态:人,狗,猪 import abc class Animal(metaclass=abc.ABCM ...

  6. Python面向对象(三)

    一.绑定方法与非绑定方法 一.绑定方法:绑定给谁就应该由谁来调用,谁来调用就会将谁当作第一个参数传入 1.绑定给对象的方法:类中定义的函数默认就是绑定给对象的 2.绑定给类的方法:为类中定义的函数加上 ...

  7. Python面向对象三要素-多态

    Python面向对象3要素-多态 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.  一.多态概述 OCP原则:多用“继承”,少修改. 继承的用途:在子类上实现对基类的增强,实现多态. ...

  8. javascript面向对象(三):非构造函数的继承

    本文来自阮一峰 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承". 今天是最后一个部分,介绍不使用构造函数实现"继承" ...

  9. Objective-C面向对象(三)

    1.类的继承 OC的继承是单继承,每个子类只有一个直接父类 1.1 继承的特点 OC继承的语法 @interface SubClass :SuperClass { //成员变量定义 } //方法定义部 ...

  10. Java学习笔记10(面向对象三:接口)

    接口: 暂时可以理解为是一种特殊的抽象类 接口是功能的集合,可以看作是一种数据类型,是比抽象类更抽象的"类" 接口只描述所应该具备的方法,并没有具体实现,具体实现由接口的实现类(相 ...

随机推荐

  1. SSM整合pom.xml和导包

    SSM 整合-自己写的 SSM Spring +SpringMVC+Mybatis 配置 及pom.xml SSM框架(spring+springMVC+Mybatis) pom.xml文件 mave ...

  2. Java设计模式(16)中介模式(Mediator模式)

    Mediator定义:用一个中介对象来封装一系列关于对象交互行为. 为何使用Mediator模式/中介模式 各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉 ...

  3. dplyr包

    是Hadley Wickham的新作,主要用于数据清洗和整理,该包专注dataframe数据格式,从而大幅提高了数据处理速度,并且提供了与其它数据库的接口:tidyr包的作者是Hadley Wickh ...

  4. 【转】两款 Web 前端性能测试工具

    前段时间接手了一个 web 前端性能优化的任务,一时间不知道从什么地方入手,查了不少资料,发现其实还是蛮简单的,简单来说说. 一.前端性能测试是什么? 前端性能测试对象主要包括: HTML.CSS.J ...

  5. What is systemvolumeinformation? delete it?

    System Volume Information完全可以删除 许多人为了自己的电脑上的System Volume Information不知道而苦恼..我再此给大家介绍一下希望能给你点帮助.. Sy ...

  6. MySQL迁移数据库(mysqldump)

    一.导出导入所有数据库的数据 1.导出 mysqldump -u root -p123456 --all-databases > all.sql 2.导入 mysql -u root -p123 ...

  7. elasticsearch系列六:聚合分析(聚合分析简介、指标聚合、桶聚合)

    一.聚合分析简介 1. ES聚合分析是什么? 聚合分析是数据库中重要的功能特性,完成对一个查询的数据集中数据的聚合计算,如:找出某字段(或计算表达式的结果)的最大值.最小值,计算和.平均值等.ES作为 ...

  8. e799. 限制JSlider的数值在标记以内

    By default, the slider can take on any value from the minimum to the maximum. It is possible to conf ...

  9. Unity GUI(uGUI)使用心得与性能总结

    Unity GUI(uGUI)使用心得与性能总结 作者 kingshijie 关注 2015.09.26 15:35 字数 3686 阅读 28031评论 10喜欢 49 背景和目的 小哈接触Unit ...

  10. [原创] Keil uVision5 下载程序 add flash programming algorithm选项缺少需要的算法解决办法

    MDK开发环境从V4升级到V5后,支持包不再是集成到开发环境当中,而是封装在PACK中,需要自行安装,比较麻烦. 搭建MDK开发环境以及破解的方法,在前面的文章中有详细说明,这里不再赘述,有兴趣的可以 ...