一、自定義類
定義類:type 類名 struct
1.1仲智、定義類
// user 類
type user struct {
name string
email string
ext int
privileged bool
}
// admin 類
type admin struct {
// 自定義類
person user
// 內(nèi)置類型
level string
}
1.2买乃、實(shí)例化類
// 1. 創(chuàng)建 user 變量,所有屬性初始化為其零值
var bill user
fmt.Println(bill) // { 0 false}
// 2. 創(chuàng)建 user 變量钓辆,并初始化屬性值
lisa := user{
name: "nana",
email: "117@qq.com",
ext: 123,
privileged: true,
}
fmt.Println(lisa) // {nana 117@qq.com 123 true}
// 直接使用屬性值剪验,屬性值的順序要與 struct 中定義的一致
lisa2 := user{"nana", "117@qq.com", 123, true}
fmt.Println(lisa2) // {nana 117@qq.com 123 true}
// 3. 含有自定義類型的 struct 進(jìn)行初始化
fred := admin{
person: user{
name: "nana",
email: "117@qq.com",
ext: 123,
privileged: true,
},
level: "super",
}
fmt.Println("fred:", fred) // fred: {{nana 117@qq.com 123 true} super}
二肴焊、方法
- 方法的定義方法實(shí)際上也是函數(shù),只是在聲明時(shí)功戚,在關(guān)鍵字 func 和方法名之間增加了一個(gè)參數(shù)
- 普通的函數(shù)定義
func 方法名(入?yún)? 返回值
- 自定義類型的方法定義
func (接收者) 方法名(入?yún)? 返回值
- 方法的值傳遞和指針傳遞
func (u user) notify()
拷貝一份 userfunc (u *user) changeEmail(newEmail string)
傳遞指針(即地址)娶眷,內(nèi)部改變會(huì)影響外部
type user struct {
name string
email string
}
// 普通的函數(shù)定義 "func 方法名(入?yún)? 返回值"
// 自定義類型的函數(shù)定義 "func (接收者) 方法名(入?yún)? 返回值"
// 值傳遞,拷貝一份 user
func (u user) notify() {
fmt.Println("pass-by-value", u.name, u.email)
u.email = "0@qq.com"
}
// 傳遞指針(即地址)啸臀,內(nèi)部改變會(huì)影響外部
func (u *user) changeEmail(newEmail string) {
// 不需要 (*u).email
u.email = newEmail
}
func main() {
// 1. user類型的值可以用來(lái)調(diào)用使用值接收者聲明的方法
bill := user{"bill", "1@qq.com"}
bill.notify() // {"bill", "1@qq.com"}
fmt.Println("1", bill.email) // "1@qq.com"
// 2. 指向 user 類型值的指針也可以用來(lái)調(diào)用使用值接收者聲明的方法
lisa := &user{"lisa", "2@qq.com"}
// 等價(jià)于 (*lisa).notify()
// 注意:把 lisa 指針指向的 user 對(duì)象復(fù)制了一份,"再?gòu)?qiáng)調(diào)一次届宠,notify 操作的是一個(gè)副本,只不過(guò)這次操作的是從 lisa 指針指向的值的副本乘粒。"
lisa.notify() // {"lisa", "2@qq.com"}
fmt.Println("2", lisa.email) // "0@qq.com"(錯(cuò)) 2@qq.com(對(duì))
// 3.user 類型的值可以用來(lái)調(diào)用使用指針接收者聲明的方法
// 等價(jià)于 (&bill).changeEmail ("100@qq.com")豌注,注意 changeEmail 接收的是一個(gè)指針
bill.changeEmail("100@qq.com")
fmt.Println("3", bill.email) // "100@qq.com"
// 4.指向 user 類型值的指針可以用來(lái)調(diào)用使用指針接收者聲明的方法
lisa.changeEmail("200@qq.com")
fmt.Println("4", lisa.email) // "200@qq.com"
}
注意:著重注意2,“再?gòu)?qiáng)調(diào)一次灯萍,notify 操作的是一個(gè)副本轧铁,只不過(guò)這次操作的是從 lisa 指針指向的值的副本
〉┟蓿”
三齿风、嵌入類型
- Go 語(yǔ)言允許用戶擴(kuò)展或者修改已有類型的行為。這個(gè)功能是通過(guò)嵌入類型 type embedding 完成的绑洛。嵌入類型是將已有的類型直接聲明在新的結(jié)構(gòu)類型里救斑。被嵌入的類型被稱為新的外部類型的內(nèi)部類型。
- Java 通痴矬裕可以通過(guò)繼承或組合的方式實(shí)現(xiàn)嵌入類型要實(shí)現(xiàn)的功能系谐。
"要嵌入一個(gè)類型,只需要聲明這個(gè)類型的名字就可以了"
讨跟,即 user 而不是 u user, u user 是聲明字段- 內(nèi)部類型的方法可以被提升到外部類型直接使用
type user struct {
name string
email string
}
// 注意該方法是 user 的方法(接收者為 user)
func (u *user) notify() {
fmt.Println("notify", *u)
}
type admin struct {
// 嵌入類型: "要嵌入一個(gè)類型鄙煤,只需要聲明這個(gè)類型的名字就可以了"
// 注意:不是 u user, u user 是聲明字段
// user 是外部類型 admin 的內(nèi)部類型
user
level string
}
func main() {
ad := admin{
user: user{"nana", "110@qq.com"},
level: "super",
}
// 我們可以直接訪問(wèn)內(nèi)部類型的方法
ad.user.notify() // notify {nana 110@qq.com}
// 內(nèi)部類型的方法也被提升到外部類型
ad.notify() // notify {nana 110@qq.com}
}