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. 两个项目之间通过 RestTemplate 进行调用

    A服务发出请求: @RequestMapping("/jqgridjsondata.json") @ResponseBody public String jqgridJsonDat ...

  2. Navi.Soft31.开发工具(含下载地址)

    1系统简介 1.1功能简述 在软件开发过程中,我们需要经常对字符串.文件.数据库操作.有时需要浏览Json格式串,有时需要浏览Xml格式串,有时需要读取txt或excel文件,有时需要对数据库访问.本 ...

  3. Java设计模式(10)代理模式(Proxy模式)

    理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...

  4. 引用dataframe的值为什么会不同

    在R语言中,通常有一些操作符可以来提取对象的子集,如以下三种: 1.“[” 单层方括号,返回的对象与原对象类型相同,它也可以返回一个对象中的多个元素: 2.“[[” 双层方括号,用来从列表(list) ...

  5. 移动互联网App兼容性测试

    我建议大家也可以参考一些针对App监测和统计的网站,都非常有意义,具体如下: 友盟品牌手机排行榜  http://www.umeng.com/ 移动观象台   https://www.talkingd ...

  6. Speeding up image loading in WPF using thumbnails

    Technorati Tags: wpf, thumbnails, image, performance, slow, BitmapImage During a recent WPF session ...

  7. 无法加载 Parallels 驱动器

    解决 最新版 mac 系统 无法使用未签名第三驱动 10.12.多 我的情况是 10.11.4 Beta (15E27e) 使用绿联usb网卡不正常. 下面的命令为检测驱动是否装载的一些命令.sudo ...

  8. 自然语言交流系统 phxnet团队 创新实训 项目博客 (四)

    刚开始做时,一点头绪都没有,整天的上网找资料,各种谷歌百度,各种博客论坛,搜索的关键词也无非是智能自然语言交流.智能机器人.中文问答系统等等等等.而我们的思路也是些零散的,例如我们知道会用到分词,会用 ...

  9. android 8 wifi wifi 扫描过程

    查看一下android wifi扫描的过程. packages\apps\Settings\src\com\android\settings\wifi\WifiSettings.java public ...

  10. OpenStack提交代码的review流程

    本文整理向openstack社区提交代码的基本流程,以及社区一些介绍资料.如有转载,请注明出处! 先放张图说明一下OpenStack的code review的大体流程: 对OpenStack提交代码更 ...