非零基础速成 Go_面向对象之结构体、接口与断言
结构体/类
在 Java 面向对象中,class 来表示一个类,在 Go 中,跟 C 中的结构体一样,但面向对象特性做的
常好,在 Go 中以 struct 用来表示一个类,它也有接口、实现、集成等概念,一起来看看吧
package main
import "fmt"
type Hero struct {
//首字母大写代表公有属性 小写代表私有属性 无法被外部类获得 如外部包 Hero.level 是不被允许的 但可以通过 get 方法获得
Name string
Ad int
level int
}
//this 代表谁能调用这个方法 只有Hero对象可以调用 Show 方法
//方法首字段用大写代表共有功法 跟 Java 中的 public 一样 小写则是 private
func (this *Hero) Show() {
fmt.Println(this.Name)
fmt.Println(this.Ad)
fmt.Println(this.level)
}
//这个方法是 public
func (this *Hero) GetName() string {
return this.Name
}
//private 屏蔽外部包的访问
func (this *Hero) SetName(newName string) {
this.Name = newName
}
func main() {
hero := Hero{Name: "zhangsan", Ad: 100}
hero.Show()
hero.setName("lisi")
hero.Show()
}
强调:在 Go 语言中,函数名的首字母大小写非常重要,它被来实现控制对方法的访问权限。
- 当方法的首字母为大写时,这个方法对于所有包都是Public,其他包可以随意调用
- 当方法的首字母为小写时,这个方法是Private,其他包是无法访问的。
Go语言通过首字母的大小写来控制访问权限。无论是方法,变量,常量或是自定义的变量类型,如果首字母大写,则可以被外部包访问,反之则不可以。
继承
package main
import "fmt"
// ---------------------父类---------------------
type Human struct {
name string
sex string
}
//Human对象的 Eat方法
func (this *Human) Eat() {
fmt.Println("Human eating ...")
}
func (this *Human) Walk() {
fmt.Println("Human walking...")
}
// ------------------子类---------------
type SuperMan struct {
//代笔继承类Human
Human
level int
}
//方法重写
func (this *SuperMan) Eat() {
fmt.Println("Superman eating ...")
}
//子类的新方法
func (this *SuperMan) Fly() {
fmt.Println("Superman flying ...")
}
//子类新增方法
func (this *SuperMan) Print() {
fmt.Println("name = ",this.name)
fmt.Println("sex= ",this.sex)
fmt.Println("level = ",this.level)
}
func main() {
h := Human{"zhang3","female"}
h.Eat()
h.Walk()
s := SuperMan{Human{"lisi" ,"female"},88}
//walk方法没有重写 所以调用的是父类的
s.Walk()
s.Eat()
s.Fly()
s.Print()
}
Human eating …
Human walking…
Human walking…
Superman eating …
Superman flying …
name = lisi
sex= female
level = 88
接口
package main
import "fmt"
//定义接口
type Animal 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"
}
//狗 同样实现接口方法
type Dog struct {
color string
}
func (this *Dog) Sleep() {
fmt.Println("Dog is Sleep")
}
func (this *Dog) GetColor() string {
return this.color
}
func (this *Dog) GetType() string {
return "Dog"
}
// 多态
// 究竟是猫还是狗 取决于传递进来的是猫还是狗
func showAnimal(animal Animal) {
animal.Sleep()
fmt.Println("color = ", animal.GetColor())
fmt.Println("kind = ", animal.GetType())
}
func main() {
//接口引用 指向 子类对象
//var animal Animal
//animal = &Cat{"Green"}
//animal.Sleep()
//
//animal = &Dog{"Yellow"}
//animal.Sleep()
cat := Cat{"Green"}
dog := Dog{"Yellow"}
showAnimal(&cat)
showAnimal(&dog)
}
值传递和引用传递
在GO中 传递对象也分引用传递和值传递 如果你传递的不是地址,那么默认都是值传递
注意这点跟 Java 有一定区别 Java 如果是引用传递 那么传递的就是地址
请看 demo
package main
import "fmt"
type Book struct {
title string
auth string
}
//传递的是副本
func changeBook(book Book) {
book.auth = "666"
}
//传递的是引用
func changeBook2(book *Book) {
book.auth = "777"
}
func main() {
var book1 Book
book1.title = "Golang"
book1.auth = "zhang3"
fmt.Println(book1)
changeBook(book1)
fmt.Println(book1)
changeBook2(&book1)
fmt.Println(book1)
//
//{Golang zhang3}
//{Golang zhang3}
//{Golang 777}
}
万能类型interface{}与类型断言
package main
import "fmt"
//接收 interface{} 是万能类型
func myFunc(arg interface{}) {
fmt.Println("calld myFunc")
//如何区分这个万能类型 "类型断言"
fmt.Println(arg)
//判断 arg 是否是 string 类型
value, ok := arg.(string)
if !ok {
fmt.Println("arg is not string type")
}else {
fmt.Println("arg is string type,value = ",value)
fmt.Printf("value type is %T\n",value)
}
}
type Book struct {
auth string
}
func main() {
book := Book{"Golang"}
myFunc(book)
myFunc(100)
myFunc("Av")
}
calld myFunc
{Golang}
arg is not string type
calld myFunc
100
arg is not string type
calld myFunc
Av
arg is string type,value = Av
value type is string