go結構,結構嵌套,接口,指針的測試和結論

package main

import (
    "fmt"
)

//T是M1接受者,不是實現M2接受者
//*T是M1接受者,也是M2的接受者
//因此T對象不能夠賦值給接口對象。*T能夠

//結論:
// 1.結構T實現接口I時,若是想經過方法改變其屬性,則須要*T實現I全部方法:
// 2.嵌套結構時,編譯器會將子結構的屬性和方法拷貝給父結構,與子結構無關係了;
// 3.賦值給接口對象I1,或者接口做爲函數參數時,I1:=&T,由於是*T實現了接口I,不然報錯
type T struct {
    Name string
}

func (t T) M1(name string) {
    // 值傳遞,改變副本的值
    t.Name = name
}
func (t *T) M2(name string) {
    // 結構體指針,修改其自己
    t.Name = name
}

type Intf interface {
    M1(name string)
    M2(name string)
}

func main() {
    fmt.Println(`*****t1 := T{"t1"}`)
    t1 := T{"t1"}
    fmt.Println("M1以前:", t1.Name)
    t1.M1("name1")
    fmt.Println("M1以後:", t1.Name)
    t1.M2("name2")
    fmt.Println("M2以後:", t1.Name)

    fmt.Println(`*****t2 := &T{"t2"}`)
    t2 := &T{"t2"}
    fmt.Println("M1以前:", t2.Name)
    t2.M1("name1")
    fmt.Println("M1以後:", t2.Name)
    t2.M2("name2")
    fmt.Println("M2以後:", t2.Name)

    // T does not implement Intf (M2 method has pointer receiver)
    // var t3 Intf = t1
    var t3 Intf = &t1
    t1.Name = "t1"
    fmt.Println(`****t3 Intf = &t1`)
    fmt.Println("M1以前:", t1.Name)
    t3.M1("name1")
    fmt.Println("M1以後:", t1.Name)
    t3.M2("name2")
    fmt.Println("M2以後:", t1.Name)

    t1.Name = "t0"
    fmt.Println("test1 before", t1.Name)
    test1(&t1)
    fmt.Println("test1 after", t1.Name)
    test2(&t1)
    fmt.Println("test2 after", t1.Name)

    // 只有*S實現I,且使用接口做爲函數的參數時,須要傳遞&T,才能改變自身數據

    t1.Name = "h1"
    test3(t1)
    fmt.Println(t1.Name)

    t1.Name = "h1"
    test4(&t1)
    fmt.Println(t1.Name)

    //嵌套類型
    // 就是複製一份給新的結構,與原結構無關了
    t1.Name = "t1"
    type S struct {
        T
        age int
    }
    s1 := S{T: t1, age: 12}
    fmt.Println(s1.Name, t1.Name)
    s1.M1("s1")
    fmt.Println(s1.Name, t1.Name)
    s1.M2("s2")
    fmt.Println(s1.Name, t1.Name)

    //新結構與接口
    var I1 Intf = &s1

}

func test1(t Intf) {
    t.M1("n1")
}
func test2(t Intf) {
    t.M2("n2")
}

func test3(t T) {
    t.M2("m1")
}
func test4(t *T) {
    t.M2("m2")
}
相關文章
相關標籤/搜索