【go语言 | 第3篇】go中类的封装、继承、多态 + 反射

文章目录

  • [golang 中类的封装](#golang 中类的封装)
  • 类的继承
  • 类的多态
  • [interface{} 万能数据类型](#interface{} 万能数据类型)
  • 反射
    • [1. 变量内置 pair 结构](#1. 变量内置 pair 结构)
    • [2. 反射 reflect 机制](#2. 反射 reflect 机制)
    • [3. 结构体标签](#3. 结构体标签)
    • [4. 结构体标签在 Json 中的应用](#4. 结构体标签在 Json 中的应用)

golang 中类的封装

java 复制代码
package main

import "fmt"

// 类名首字母大写,表示其他包也可以访问
type Person struct {
	Name string   // 属性名首字母大写,表示该属性对外能够访问,否则只能类的内部访问
	Age int
	Sex string
}

func (this *Person) Show() {
	fmt.Println("姓名:", this.Name, ",年龄:", this.Age, ",性别:", this.Sex)
}

func (this *Person) GetName() string {
	return this.Name
}

func (this *Person) SetName(name string) {
	// this是调用方法对象(指针)
	this.Name = name
}

func (this Person) SetName2(name string) {
	// this是调用方法对象的一个副本
	this.Name = name
}
func main() {
	p := Person {
		Name: "张三",
		Age: 18,
		Sex: "男",
	}

	p.Show()

	fmt.Println("==============================================")
	p.SetName2("honghong")
	p.Show()

	fmt.Println("==============================================")
	p.SetName("honghong")
	p.Show()

}

注意:go 语言中,类名、属性、方法的首字母是否大写,都与其是否能被外部(其它包)访问有关,否则只能在本包内访问。

类的继承

go 复制代码
package main

import "fmt"

type Human struct {
	name string
	sex string
}

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

func (this *Human) Walk() {
	fmt.Println("Human Walking...")
}

// ===========================
// 继承:定义 SuperMan 继承自 Human
type SuperMan struct {
	// 表示继承自Human
	Human
	level int
}

// 重写 eat 方法
func (this *SuperMan) Eat() {
	fmt.Println("SuperMan Eating...============")
}

// 增加 Fly 方法
func (this *SuperMan) Fly() {
	fmt.Println("SuperMan Flying...============")
}

func main() {
	h := Human {"zhangsan", "male"}
	h.Eat()
	h.Walk()

	fmt.Println("============================================================")

	// 定义子类对象
	//s := SuperMan {Human{"lisi", "female"}, 2}
	var s SuperMan
	s.name = "lisi"
	s.sex = "female"
	s.level = 2	

	s.Eat()  
	s.Walk()
	s.Fly()
}

类的多态

go 复制代码
package main

import "fmt"

// interface
type Animal interface {
	Sleep()
	GetColor() string
	GetType() string
}

// 具体的类
type Cat struct {
	Color string
}

func (this *Cat) Sleep() {
	fmt.Println("Cat is sleeping")
}

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

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

// 具体的类
type Dog struct {
	Color string
}

func (this *Dog) Sleep() {
	fmt.Println("Dog is sleeping")
}

func (this *Dog) GetColor() string {
	return this.Color
}

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

func showAnimal (animal Animal) {
	fmt.Println(animal.GetType(), animal.GetColor())
}

func main() {
	// 多态体现:同一个接口类型的变量,可以指向不同的实现类对象
	var animal Animal
	animal = &Cat{"white"}
	animal.Sleep()

	animal = &Dog{"black"}
	animal.Sleep()

	fmt.Println("==============================================")

	// 多态体现:
	cat := Cat{"white"}	
	dog := Dog{"black"}
	showAnimal(&cat)
	showAnimal(&dog)

}

多态的要素:

  1. 有一个接口
  2. 子类要实现接口的所有接口方法,少一个都不行
  3. 父类的引用指向子类的具体数据类型

interface{} 万能数据类型

interface{} 空接口:

  1. int、string、float64... 均实现了 interface{}
  2. 可以用 interface{} 类型代表任何数据类型

interface 用于类型断言

go 复制代码
package main

import "fmt"

// interface{} 作为万能数据类型
func myFun(args interface{}) {
	fmt.Println("myFun!")
	fmt.Println(args)

	// 提供 interface{} 类型断言
	value, ok := args.(string)
	if !ok {
		fmt.Println("args is not string")
	} else {
		fmt.Println("args is string")
		fmt.Println("value = ", value)
	}
}

func main() {
	myFun(11)
	fmt.Println("====================================")
	myFun("hello")
	fmt.Println("====================================")
	myFun(true)
	fmt.Println("====================================")
	myFun(1.234)
}

反射

1. 变量内置 pair 结构

反射是通过 pair 结构来得到 type。

2. 反射 reflect 机制

通过 reflect 包动态获取 type 和 value:

e.g.1

go 复制代码
package main

import (
	"fmt"
	"reflect"
)

func PrintNum(arg interface{}) {
	fmt.Println("type is: ", reflect.TypeOf(arg))
	fmt.Println("value is: ", reflect.ValueOf(arg))
}
func main() {
	var num float64 = 1.235

	PrintNum(num)
}

e.g.2

go 复制代码
package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Id int
	Name string
	Age int
}

func (this User) Call() {
	fmt.Println("user call...")
}

func main() {
	u := User{1, "honghong", 18}

	PrintFieldsAndValues(u)
}

func PrintFieldsAndValues(input interface{}) {
	// 获取 input 的type
	inputtype := reflect.TypeOf(input)
	fmt.Println("inputtype is: ", inputtype)
	// 获取 input 的value
	inputvalue := reflect.ValueOf(input)
	fmt.Println("inputvalue is: ", inputvalue)

	fmt.Println("==========================================================")
	// 通过 type 获取里面的字段
	// 1. interface获取 type,通过 type 获取 NumFields, 遍历字段
	// 2. 得到每个 field,数据类型
	// 3. 通过 field 有一个 Interface() 方法得到 value
	for i := 0; i < inputtype.NumField(); i++ {
		field := inputtype.Field(i)
		value := inputvalue.Field(i).Interface()

		fmt.Printf("%v: %s = %v\n", field.Type, field.Name, value)
	}

	fmt.Println("==========================================================")
	// 通过 type 获取方法
	for i := 0; i < inputtype.NumMethod(); i++ {
		method := inputtype.Method(i)
		fmt.Printf("%s: %v\n", method.Name, method.Type)
	}
}

3. 结构体标签

go 复制代码
package main

import (
	"fmt"
	"reflect"
)

type resume struct {
	Name string `info:"name" doc:"我的名字"`
	sex string  `info:"sex" doc:"性别"`
}

func PrintTag(data interface{}) {
	t := reflect.TypeOf(data).Elem()

	for i := 0; i < t.NumField(); i++ {
		tagInfo := t.Field(i).Tag.Get("info")
		tagDoc := t.Field(i).Tag.Get("doc")

		fmt.Println("tag info:", tagInfo, "    tag doc:", tagDoc)
	}
}

func main() {
	var r resume

	PrintTag(&r)
}

4. 结构体标签在 Json 中的应用

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)


type Movie struct {
	Title string     `json:"title"`
	Year int		 `json:"year"`
	Price float64    `json:"rmb"`
	Actors []string  `json:"actors"`
}

func main() {
	movie := Movie {"唐顿庄园", 2000, 9.5, []string {"tom", "jerry", "lucy"}}

	// 编码 movie  结构体------------> json
	jsonStr, err := json.Marshal(movie)
	if err != nil {
		fmt.Println("json.Marshal err:", err)
		return
	}
	fmt.Printf("%s\n", jsonStr)

	// 解码 json ------------> movie 结构体
	myMovie := Movie{}
	err = json.Unmarshal(jsonStr, &myMovie)
	if err != nil {
		fmt.Println("json.Unmarshal err:", err)
		return
	}
	fmt.Printf("%v\n", myMovie)

}
相关推荐
四维碎片1 分钟前
【Qt】代理(Delegate)的使用
开发语言·qt
鹓于7 分钟前
Excel一键生成炫彩二维码
开发语言·前端·javascript
froginwe119 分钟前
MongoDB 固定集合详解
开发语言
m0_7369191021 分钟前
C++中的策略模式实战
开发语言·c++·算法
子春一21 分钟前
Flutter for OpenHarmony:构建一个智能长度单位转换器,深入解析 Flutter 中的多字段联动、输入同步与工程化表单设计
开发语言·javascript·flutter
从此不归路28 分钟前
Qt5 进阶【9】模型-视图框架实战:从 TableView 到自定义模型的一整套落地方案
开发语言·c++·qt
hssfscv34 分钟前
Javaweb学习笔记——后端实战7 springAOP
笔记·后端·学习
消失的旧时光-194335 分钟前
第九课实战版:异常与日志体系 —— 后端稳定性的第一道防线
java·后端
人道领域39 分钟前
javaWeb从入门到进阶(SpringBoot基础案例2)
java·开发语言·mybatis
Stack Overflow?Tan9040 分钟前
c++constexpr
开发语言·c++