一、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

}