1. 程式人生 > 其它 >關於golang interface中T和*T的一個小測試和思考

關於golang interface中T和*T的一個小測試和思考

首先

貼一下參考的部落格資料。
https://www.cnblogs.com/shijingxiang/articles/12201984.html

背景:

golang中使用interface實現類似於C++或者JAVA 的多型,其中比較複雜的是介面中函式呼叫者引數可能為T或者*T。
按照官方文件說明,interface中 T 型別只能處理接收者引數為 T, T型別可以呼叫接收者引數為T或者T。

結論:

interface呼叫 *T型別呼叫接收者引數為T的函式時候,做法應該是對 *T型別變數做一個 反操作 類似於下面

package main

import (
    "fmt"
)

type Submit interface {
    work()
}
type Student struct {
    Name string
}

func (s Student) work() {
    fmt.Printf("work: %p\n", &s)
    s.Name += "s"
}
func doWork(sub Submit) {
    sub.work()
    sub.work()
}

func main() {
    stu := &Student{Name: "wyh"}
    fmt.Printf("main: %p\n", stu)
    // 此處傳遞為Student指標,work函式為Student型別
    fmt.Println(stu)
    doWork(stu)
    fmt.Println(stu)
}
結果為
main: 0xc000048230
&{wyh}
work: 0xc000048260
work: 0xc000048270
&{wyh}
可以看到兩次work函式的Student不是同個地址
在以上程式碼中`sub.work()`函式被呼叫的時候,我理解編譯器做的事情為
var temp Student
temp = *(sub.(&Student)).DeepCopy()
temp.work()

可以多做一個嘗試,當work函式為接收者引數為*Student的時候,work函式每一次呼叫的s打印出來地址都是一致

思考

  • 為什麼T型別只能呼叫接收者引數為T,而不能是*T,反之*T可以呼叫T和*T。

兩個問題,後一個*T可以呼叫T和*T,原理就是上面猜測。
T型別呼叫*T會發生什麼可能,首先我覺得技術是可以做到,相當於對一個物件定址應該是沒啥問題
但為什麼Golang不支援的原因是可能定址過後,會有人手賤把它指向另一個其他物件A,假設A又不符合interface定義,會發生內部邏輯錯誤
這點的推測是從第一種情況中得出,為什麼*T呼叫T的時候,是每次都例項化一個新的物件,
不就是為了安全,而且保持一種約定,*T才能修改物件內容,T不能修改內容。