Structs and Interfaces
Structs(結構)
結構是一種使用者自定的型態,它可將不同的資料型態串在一起。
結構宣告
type rect struct {
left int32
top int32
right int32
bottom int32
}
var x rect
fmt.Println(x) // {0 0 0 0}
fmt.Println(reflect.TypeOf(x)) // main.rect
結構初始化
var a rect
a.left = 1
a.top = 2
a.right = 3
a.bottom = 4
fmt.Println(a) // {1 2 3 4}
//按照顺序提供初始化值
var b rect = rect {
1,
2,
3,
45,
}
fmt.Println(b) // {1 2 3 45}
//too few values in struct initializer
//var c rect = rect {
//1,
//2,
//}
//透過 field:value 的方式初始化 好處是可以任意順序
var d rect = rect {
left:1,
top:2,
right:3,
bottom:4,
}
fmt.Println(d) // {1 2 3 4}
var e rect = rect {
top:2,
left:1,
}
fmt.Println(e) // {1 2 0 0}
結構指標
var g1 rect = rect {1, 2, 3, 4,}
fmt.Println(g1) // {1 2 3 4}
var pointG *rect = &g1;
fmt.Println(pointG, reflect.TypeOf(pointG)) // &{1 2 3 4} *main.rect
pointG.left = 100
fmt.Println(pointG, g1) // &{100 2 3 4} {100 2 3 4}
匿名属性
// 一個struct類型的匿名屬性的方法可以通過該struct對象直接調用。
// 這個特性可以讓我們實現類似於傳統OOP中的繼承特性。
type Human struct {
name string
age int
}
type Woman struct {
Human
weight int
}
type Man struct {
name string
weight int
}
type Student struct {
Human
Man
age int
}
mark := Human {"5",9,}
fmt.Println("mark : ", mark) // mark : {5 9}
mary := Woman {Human{"5",1},9,}
fmt.Println("mary : ", mary) // mary : {{5 1} 9}
mary.Human = Human{"5",1}
mary.weight = 9
john := Student {
Human{"中", 1,},
Man{"華", 2,},
3,
}
fmt.Println("john : ", john) // john : {{中 1} {華 2} 3}
fmt.Println("john : ", john.weight) // 2
//fmt.Println("john : ", john.name) // ambiguous selector john.name
fmt.Println("john : ", john.Human.name) // 中
fmt.Println("john : ", john.Man.name) // 華
fmt.Println("john : ", john.age) // 3
fmt.Println("john : ", john.Human.age) // 1
method 定義屬於結構的方法
// 定義結構
type User struct {
name string
}
//定義屬於結構User的方法
func (user *User) SetName (newName string) {
user.name = newName
}
func (user *User) GetName() string {
return user.name
}
var user User
fmt.Println("user is: ", user) // user is: {}
user.SetName("new")
fmt.Println("user is: ", user) // user is: {new}
fmt.Println("user.name is: ", user.GetName()) // user.name is: new
method 繼承與覆寫
// 定義結構
type PowerUser struct {
User
age int
}
//定義屬於結構PowerUser的方法
func (user *PowerUser) SetName(newName string) {
user.name = newName + ":PowerUser"
}
var user PowerUser
fmt.Println("user is: ", user) // user is: {{} 0}
user.SetName("new")
fmt.Println("user.name is: ", user.GetName()) // user.name is: new:PowerUser
user.User.SetName("new")
fmt.Println("user.name is: ", user.GetName()) // user.name is: new:User
Interface(接口)
Interface定義了一個或一組method(s),這些method(s)只有函數簽名,
沒有具體的實現代碼。
若某個數據類型實現了Interface中定義的那些被稱為"methods"的函數,
則稱這些數據類型實現(implement)了interface。
// 我們再複習一下 結構 和 結構指標
type Cat struct {
name string
}
func (self *Cat) GetName() string {
return self.name
}
func (self *Cat) Run() bool {
return true
}
type Dog struct {
name string
}
func (self *Dog) GetName() string {
return self.name
}
func (self *Dog) Run() bool {
return true
}
func (self *Dog) Jump() bool {
return true
}
func test() {
var myCat Cat = Cat{name: "SuperCat"}
var myCatPoint *Cat = &myCat
var myDog Dog = Dog{"SuperDog"}
var myDogPoint *Dog = &myDog
fmt.Println(myCatPoint.GetName()) // SuperCat
fmt.Println(myDogPoint.GetName()) // SuperDog
// myCatPoint = &myDog // cannot use &myDog (type *Dog) as type *Cat in assignment
}
// 定義接口類型 Human
type IAnimal interface {
GetName() string
Run() bool
}
func test2() {
var myCat Cat = Cat{name: "SuperCat"}
var myDog Dog = Dog{"SuperDog"}
// 接口的宣告要一致(回傳型別 函式名稱 參數數量與型別)
var myAnimal IAnimal
myAnimal = &myCat
fmt.Println(myAnimal.GetName()) // SuperCat
myAnimal = &myDog
fmt.Println(myAnimal.GetName()) // SuperDog
fmt.Println(myAnimal.Run()) // true
// fmt.Println(myAnimal.Jump())
// myAnimal.Jump undefined (type IAnimal has no field or method Jump)
}
// 定義接口類型 Human
type IHuman interface {
GetName() string
GetAge() int
}
// 定義接口類型 Man
type IMan interface {
IHuman // Man 接口中嵌入了 Human 接口 , Man 會獲取 Human 所有方法
GetWeight() int
// GetAge() int // duplicate method GetAge
}
// 定義結構 Student
type Student struct {
name string
age int
weight int
}
// 定義結構 Student 的方法
func (self* Student) GetName() string {
return self.name
}
func (self* Student) GetAge() int {
return self.age
}
func (self* Student) GetWeight() int {
return self.weight
}
// Student 實現了 Human 和 Man 兩個接口
mark := Student {
name : "mark_student",
age : 20,
weight : 65,
}
var i_human IHuman
i_human = &mark
fmt.Println(i_human, reflect.TypeOf(i_human)) // &{mark_student 20 65} *main.Student
fmt.Println(i_human.GetName()) // mark_student
var i_man IMan
i_man = &mark
fmt.Println(i_man, reflect.TypeOf(i_man)) // &{mark_student 20 65} *main.Student
fmt.Println(i_man.GetName()) // mark_student
fmt.Println(i_man.GetAge()) // 20
fmt.Println(i_man.GetWeight()) // 65