一、OOP特性
Go語言中的OOP特性
- 結構體:在Go中,結構體用于定義復合類型,類似于其他語言中的類。它可以包含字段(屬性)和方法(行為)。
- 方法:Go允許為任何自定義類型(包括結構體)定義方法,這與傳統OOP語言中類的方法類似。
- 接口:接口是方法的集合,實現了這些方法的類型即實現了該接口。Go的接口提供了一種靈活的方式來進行多態操作
- 組合而非繼承:Go提倡使用組合而非繼承來重用代碼。你可以將一個結構體嵌入到另一個結構體中,以達到類似繼承的效果
二、普通版本OOP
package mainimport "fmt"//定義文件操作者接口
type FileOperator interface {read()write()
}//定義文件結構體
type File struct {path stringsize intlabel string
}//定義XMLFile結構體,繼承File結構體
type XMLFile struct {Fileowner string
}// 定義File結構體的方法read
func (file File) read() {fmt.Println(file.label, "讀取文件")
}// 定義File結構體的方法write
func (file File) write() {fmt.Println(file.label, "寫入文件")
}// 定義函數useInterface,函數與方法的區別:函數不需要接收者,
// 方法需要接收者,上面read和write方法的接收者是File結構體的實例
// 該函數參數為實現了FileOperator接口的實例
func useInterface(fileOperator FileOperator) {fileOperator.read()fileOperator.write()
}// 重寫父結構體write方法
func (xml XMLFile) write() {fmt.Println(xml.label, "重寫父結構體write方法,寫入文件")
}func main() {// 實例化File結構體commonlFile := File{path: "/root",size: 3000,label: "普通文件",}// 調用接口函數,commonlFile實現了接口的所有方法,所以能夠作為參數傳入useInterface(commonlFile)// 實例化xmlFile結構體,并實例化父結構體,File也可以直接用上面的父實例commonlFile,如下:// xmlFile := XML{// owner: "root",// File: commonlFile// }xmlFile := XMLFile{owner: "root",File: File{path: "/home",size: 1000,label: "xml文件",},}// 調用接口函數,傳入子結構體實例,子結構體重寫了write方法useInterface(xmlFile)
}
輸出?
普通文件 讀取文件
普通文件 寫入文件
xml文件 讀取文件
xml文件 重寫父結構體write方法,寫入文件
?
三、帶指針的OOP
指針的好處:
1. 性能優化
減少內存拷貝:當你將一個大結構體或數組傳遞給函數時,如果不使用指針而是直接傳遞值,則會創建該數據的一個副本。對于大型數據結構,這可能導致顯著的性能開銷。通過使用指針,你可以避免這種不必要的復制,從而提高性能。
2. 修改原值的能力
改變調用者的數據:當函數參數是指針時,函數內部對參數所做的任何更改都會反映在調用者的數據上。這是因為函數接收的是實際數據的地址而不是其副本。這對于需要返回多個結果或者需要修改外部狀態的函數非常有用。
3. 高效的結構體操作
在處理結構體時,如果結構體較大,使用指針可以避免大量的內存復制。此外,在并發編程中,通過指針共享數據結構是常見做法,盡管需要注意同步問題以避免競態條件。
4. 動態分配內存
使用new()或make()等內置函數動態分配內存,并通過指針訪問這塊內存,可以使你的程序更加靈活。例如,當你不知道程序運行時需要多少元素的切片或映射時,可以通過指針來管理動態增長的數據結構。
?
?
package mainimport "fmt"//定義文件操作者接口
type FileOperator interface {read()write()
}//定義文件結構體
type File struct {path stringsize intlabel string
}//定義XMLFile結構體,繼承File結構體
type XMLFile struct {*Fileowner string
}// 定義File結構體的方法read
func (file *File) read() {fmt.Println(file.label, file.path, "讀取文件")
}// 定義File結構體的方法write
func (file *File) write() {fmt.Println(file.label, file.path, "寫入文件")
}// 定義修改文件路徑方法
func (file *File) modifyPath(newPath string) {file.path = newPath
}// 定義函數useInterface,函數與方法的區別:函數不需要接收者,
// 方法需要接收者,上面read和write方法的接收者是File結構體的實例
// 該函數參數為實現了FileOperator接口的實例
func useInterface(fileOperator FileOperator) {fileOperator.read()fileOperator.write()
}// 重寫父結構體write方法
func (xml *XMLFile) write() {fmt.Println(xml.label, "重寫父結構體write方法,寫入文件")
}func main() {// 實例化File結構體commonlFile := File{path: "/root",size: 3000,label: "普通文件",}// 調用接口函數,commonlFile實現了接口的所有方法,所以能夠作為參數傳入useInterface(&commonlFile)// 實例化xmlFile結構體,并實例化父結構體,File也可以直接用上面的父實例commonlFile,如下:// xmlFile := XML{// owner: "root",// File: &commonlFile// }xmlFile := &XMLFile{owner: "root",File: &File{path: "/home",size: 1000,label: "xml文件",},}xmlFile.modifyPath("/root/xml")// 調用接口函數,傳入子結構體實例,子結構體重寫了write方法useInterface(xmlFile)
}
輸出
普通文件 /root 讀取文件
普通文件 /root 寫入文件
xml文件 /root/xml 讀取文件
xml文件 重寫父結構體write方法,寫入文件
?