文章目录
- [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)
}

多态的要素:
- 有一个接口
- 子类要实现接口的所有接口方法,少一个都不行
- 父类的引用指向子类的具体数据类型
interface{} 万能数据类型
interface{} 空接口:
- int、string、float64... 均实现了 interface{}
- 可以用 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)
}
