1. 值與引用
varName2 = varName1
varName2.funcName()
如果 varName2 有變化,varName1 無變化,則爲值類型(傳遞)
如果 varName2 有變化,varName1 有變化,則爲引用類型(傳遞)
2. Method
格式:
func (r [*]ReceiverType) funcName(param) (result) {...}
注:a. r 爲struct對象的接收者,接收者不同,方法也不同
b. r 可以爲值傳遞也可以爲引用傳遞
c. param 和 result 可有可無,與普通函數一樣
d. 調用方法,用 "." 連接,即 r.funcName()
e. func (r *ReceiverType) funcName()和 func (r ReceiverType) funcName 不能同時存在(此處funcName相同)
f. method 可以用於所有的類型
例:
type Circle struct {
radius float64
}
func main() {
var c1 Circle
c1.radius = 10.00
fmt.Println("Area of Circle(c1) = ", c1.getArea())
}
//該 method 屬於 Circle 類型對象中的方法
func (c Circle) getArea() float64 {
//c.radius 即爲 Circle 類型對象中的屬性
return 3.14 * c.radius * c.radius
}
用面向對象的方式表示,struct == class,struct 中聲明的元素爲成員屬性,Circle 作爲接收者的函數爲成員方法
即 Circle 類名,radius 與 getArea() 分別是 Circle 類對象 c1 的成員屬性和成員方法
例1 (值傳遞):
type Circle struct {
radius float64
}
func main() {
var c1 Circle
c1.radius = 10.00
fmt.Println("main(): radius = ", c1.radius)
fmt.Println("Area of Circle(c1) = ", c1.getArea())
}
func (c Circle) getArea() float64 {
fmt.Println("getArea(): radius = ", c.radius)
return 3.14 * c.radius * c.radius
}
func (c Circle) setRadius(r float64) {
c.radius = r
fmt.Println("setRadius(): radius = ", c.radius)
}
結果:setRadius(): radius = 10
main(): radius = 0
getArea(): radius = 0
Area of Circle(c1) = 0
例2 (引用傳遞)
type Circle struct {
radius float64
}
func main() {
var c2 Circle
c2.setRadius(10.00)
fmt.Println("main(): radius = ", c2.radius)
fmt.Printf("Radius of Circle(c2) = %.2f, area = %.2f", c2.radius, c2.getArea())
}
func (c *Circle) setRadius(r float64) {
c.radius = r
fmt.Println("setRadius(): radius = ", c.radius)
}
func (c *Circle) getArea() float64 {
fmt.Println("getArea(): radius = ", c.radius)
return 3.14 * c.radius * c.radius
}
結果:setRadius(): radius = 10
main(): radius = 10
getArea(): radius = 10
Radius of Circle(c2) = 10.00, area = 314.00
補:
method可用於所有類型
定義格式:
type 自定義類型 類型
如: type Integer int,類似於給 int 定義一個別名,但是此時的 Integer 與 struct 定義的類型使用方法一樣,把它當作一個類,可以爲其添加方法
例:
type Integer int
func main() {
var i Integer
fmt.Println(i.getType())
fmt.Println(Integer.getType(i))
Integer.Print(i, "I am Int")
}
func (i Integer) getType() string {
return "Integer == int"
}
func (i Integer) Print(s string) {
fmt.Println(s)
}
結果:Integer == int
Integer == int
I am Int
注:
a. 接收者爲 typeName,而不是 *typeName 時,調用方法 varName.funcName(param) 與 typeName.funcName(varName, param) 一樣,如果是 *typeName 則不能後者訪問
b. 如果者爲 *typeName 時,通過 varName.funcName() 訪問時,等於 (&varName).funcName(),即可以不用在 varName 前面加上 "&" 取地址
3. Method繼承與重載
匿名字段就類似於面向對象編程中的繼承成員屬性,也可以重載成員屬性,method 同樣可以繼承和重載
3.1 繼承示例:
類似於調用父類中有而子類中沒有的方法
沒有面向對象中的private protected public關鍵字(通過方法名首字母大小寫來判斷)
type Person struct {
name string
age int
}
type Employee struct {
Person
salary int
}
func main() {
// var em1 Employee = Employee{Person{"rain", 23}, 5000}
em1 := Employee{Person{"Rain", 23}, 5000}
em1.printMsg()
}
func (p Person) printMsg() {
fmt.Println("I am ", p.name, " , and my age is ", p.age)
}
結果:I am Rain , and my age is 23
3.2 重載示例
重載方法,通過 varName.funcName() 訪問時,也採用最外層優先訪問的原則,也類似於面向對象中調用本類中的方法
通過 varName.匿名字段.funcName() 訪問指定匿名字段中的方法,類似於面向對象中調用父類中的方法
type Person struct {
name string
age int
}
type Employee struct {
Person
salary int
}
func main() {
// var em1 Employee = Employee{Person{"rain", 23}, 5000}
em1 := Employee{Person{"Rain", 23}, 5000}
em1.printMsg() //調用最外層(本類)的方法
em1.Person.printMsg()//調用指定匿名字段(父類)的方法
}
func (p Person) printMsg() {
fmt.Println("I am ", p.name, " , and my age is ", p.age)
}
func (e Employee) printMsg() {
fmt.Printf("I am %s, my age is %d, and my salary is %d. \n", e.name, e.age, e.salary)
}
結果:{{rain 23} 5000}
I am rain, my age is 23, and my salary is 5000.
I am rain , and my age is 23