GO语言基础(三) | 青训营

76 阅读3分钟

1.继承

父类:

type Human struct {
    name string
    sex
    string
}

子类: SuperMan子类继承Human父类,将Human写在SuperMan结构体中即可继承

type SuperMan struct {
    Human//SuperMan类继承了Human类的方法
    level 
    int
}

重定义父类的方法Eat() 使用子类的*SuperMan

func (this *SuperMan) Eat() {
    fmt.Println("SuperMan.Eat()...") 
}

子类的新方法

func (this *SuperMan) Fly(){
    fmt.Println("SuperMan.Fly()...") 
}

定义一个子类对象

s :=SuperMan{Human{"li4","female"},88}

2.多态

接口,本质是一个指针

type AnimalIF interface { 
    Sleep()
    GetColor() string //获取动物的颜色 
    GetType() string//获取动物的种类 
    

具体的类

type Cat struct {
    color string //猫的颜色
}
func (this *Cat) Sleep(){ fmt.Println("Cat is Sleep") }

func(this *Cat) GetColor() string { return this.color }

func(this *Cat) GetType() string{ return "Cat" }

创建对象

var animal AnimalIF//接口的数据类型,父类指针 animal=&Cat{"Green"}
animal.Sleep()//调用的就是Cat的Sleep()方法,多态的现象

3.空接口和类型断言

Interface{}是万能数据类型

Interface{}用作形参:

func myFunc(arg interface{}) {
    fmt.Println("myFunc is called...") 
    fmt.Println(arg)
 }

image.png

4.pair结构

image.png

image.png

5.反射

image.png 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

反射机制就是在运行时动态的调用对象的方法和属性

  • 变量包括(type, value)两部分
  • type 包括 static type和concrete type. 简单来说 static type是你在编码是看见的类型(如int、string),concrete type是runtime系统看见的类型
  • 类型断言能否成功,取决于变量的concrete type,而不是static type. 因此,一个 reader变量如果它的concrete type也实现了write方法的话,它也可以被类型断言为writer.

只有interface类型才有反射一说。

image.png img转存失败,建议直接上传图片文件

reflect.Value是通过reflect.ValueOf(X)获得的,只有当X是指针的时候,才可以通过reflec.Value修改实际变量X的值,即:要修改反射类型的对象就一定要保证其值是“addressable”的。

image.png

  1. newValue.CantSet()表示是否可以重新设置其值,如果输出的是true则可修改,否则不能修改,修改完之后再进行打印发现真的已经修改了。
package main

import (

"fmt"

"reflect"

)

type User struct {

Id int

Name string

Age int

}

func (u User) ReflectCallFuncHasArgs(name string, age int) {

fmt.Println("ReflectCallFuncHasArgs name: ", name, ", age:", age, "and origal User.Name:", u.Name)

}

func (u User) ReflectCallFuncNoArgs() {

fmt.Println("ReflectCallFuncNoArgs")

}

如何通过反射来进行方法的调用?

本来可以用u.ReflectCallFuncXXX直接调用的,但是如果要通过反射,那么首先要将方法注册,也就是MethodByName,然后通过反射调动mv.Call


func main() {

user := User{1, "Allen.Wu", 25}
  1. 要通过反射来调用起对应的方法,必须要先通过reflect.ValueOf(interface)来获取到reflect.Value,得到“反射类型对象”后才能做下一步处理
getValue := reflect.ValueOf(user)

一定要指定参数为正确的方法名

  1. 先看看带有参数的调用方法
methodValue := getValue.MethodByName("ReflectCallFuncHasArgs")

args := \[]reflect.Value{reflect.ValueOf("wudebao"), reflect.ValueOf(30)}

methodValue.Call(args)

一定要指定参数为正确的方法名

  1. 再看看无参数的调用方法
methodValue = getValue.MethodByName("ReflectCallFuncNoArgs")

args = make(\[]reflect.Value, 0)

methodValue.Call(args)

运行结果:

ReflectCallFuncHasArgs name: wudebao , age: 30 and origal User.Name: Allen.Wu

ReflectCallFuncNoArgs

image.png Golang的反射很慢