一、struct 结构体
1.使用type关键字可以定义新的数据类型。
2.定义结构体,如:
type Book struct{
title string
author string
}
3.定义并使用结构体变量:var book1 Book,book1.title = "abcd",book1.author = "efgh"。
4.结构体作为函数参数,传递的是一个结构体副本,传递结构体指针时才会对该结构体对象进行修改。
二、面向对象
1.Go语言中的类,就是通过结构体绑定方法。如定义如下结构体:
type Hero struct{
name string
id int
level int
}
(1)定义一个方法:func (this Hero) setName(name string) { this.name = name }。此方法中this Hero表示当前方法绑定在了Hero结构体上,方法内部可以通过this.name调用此Hero对象中的name属性。
(2)通过如hero := Hero{name : "zhangsan", id : 1, level :1}这样的语句创建Hero对象。
(3)如果调用(1)中的方法 hero.setName("lisi")是无法真正修改对象hero的name属性的,因为传参为hero对象的一个拷贝,只可读不可写。可以修改方法为:func (this *Hero) setName(name string) { this.name = name },这样即可实现写方法。
(4)如果类名首字母大写,其他包即可使用此对象;如果类中属性名大写,表示此对象的该属性为public属性,对外可访问;方法首字母大写同理,其他包可调用。(首字母大小写可表示此类、属性、方法是否公有/私有)
2.继承
(1)首先定义基本类和方法:
type Human struct{
Name string
Sex string
}
func (this *Human) Eat(){
fmt.Println("Human Eat");
}
func (this *Human) Walk(){
fmt.Println("Human Walk");
}
创建Human对象:human := Human{"zhangsan", "man"},调用human.Eat()以及human.Walk()会分别输出不同的字符串,表示不同行为。
(2)定义SuperMan类继承Human类:
type SuperMan struct{
Human //写在这里表示SuperMan类继承Human类。
Level int
}
重写父类方法Eat:
func (this *SuperMan) Eat(){
fmt.Println("SuperMan Eat");
}
定义新方法Fly:
func (this *SuperMan) Fly(){
fmt.Println("SuperMan Fly");
}
定义子类对象:s := SuperMan{Human{"lisi", "man"}, 88},调用方法同上;或者通过如下方法定义:
var s SuperMan
s.Name = "lisi"
s.Sex = "Man"
s.Level = 88
3.多态
(1)使用interface关键字定义接口:
type AnimalIF interface{
Sleep()
GetColor() string //获取动物的颜色
GetType() string //获取动物的种类
}
interface本质是一个指针。
(2)如要定义实体类实现AnimalIF接口,不必按照继承的写法,只需在实体类内部实现接口的全部方法即可:
type Cat struct{
Color string
Type string
}
//如下所示,Cat实体类实现了AnimalIF接口里的全部方法,说明Cat实体类实现了该接口。在Go语言中interface的实现是隐性的,一个结构体类型如果实现了某interface中的所有方法,则说明了这个interface。
func (this *Cat) Sleep() {
fmt.Println("Cat is sleeping")
}
func (this *Cat) GetColor() string{
return this.Color
}
func (this *Cat) GetType() string{
return this.Type
}
(3)定义Dog实体类,同样实现AnimalIF接口中的全部方法:
type Dog struct{
Color string
Type string
}
//如下所示,Cat实体类实现了AnimalIF接口里的全部方法,说明Cat实体类实现了该接口
func (this *Dog) Sleep() {
fmt.Println("Dog is sleeping")
}
func (this *Dog) GetColor() string{
return this.Color
}
func (this *Dog) GetType() string{
return this.Type
}
(4)创建Cat对象和Dog对象:
var animal AnimalIF //接口的数据类型,父类指针
animal = &Cat{"green", "cat"}
animal.Sleep()
animal = &Dog{"yellow", "dog"}
animal.Sleep()
此时会依序输出Cat is sleeping和Dog is sleeping,实现多态。
(5)或者定义方法:
func showAnimal(animal AnimalIF){
animal.Sleep()
}
创建对象:cat := Cat{"green", "cat"}, dog := Dog{"yellow", "dog"},可分别调用showAnimal方法:
showAnimal(&cat)
showAnimal(&dog)
效果同(4)。
4.interface{}表示空接口,为万能数据类型,所有数据类型(包括基本数据类型)几乎都实现了interface{}接口。如定义函数:
func myFunc(arg interface{}){
fmt.Println(arg)
}
此时myFunc函数可以传入任意数据类型的参数,若想在方法体内区分引用的数据类型到底是什么,go语言给interface{}提供了类型断言机制,如:
value, OK := arg.(string)可判断arg传入的参数是否为string,如果是string,则OK此时为true,value为arg的值。
三、json字符串和Golang中的结构体对象相互转换
1.若想完成转换,结构体中属性名需大写,否则json包无法读取。
2.使用json.Marshal(s)方法,可以把结构体对象s转换成对应的json字符串,返回值为[]byte切片和一个error对象。
3.使用json.Unmarshal(bytes, &s)方法,可以把json字符串bytes转换成结构体对象s,参数bytes为一个[]byte切片,&s为结构体对象的地址,返回值为一个error对象。
4.结构体标签:在定义结构体时,在属性名后用反引号``指定该属性对应的json序列中的字段名,如:
type Hero struct{
Name string `json: "name"`
Id int `json: "id"`
Level int
}