Go語言開發(四)、Go語言物件導向

來源:互聯網
上載者:User

標籤:UNC   後序遍曆   print   多態   調用   windows   pat   public   import   

Go語言開發(四)、Go語言物件導向一、結構體和方法1、結構體的定義

在結構體中可以為不同項定義不同的資料類型。
結構體是由一系列具有相同類型或不同類型的資料構成的資料集合。
結構體定義需要使用type和struct語句。struct語句定義一個新的資料類型,結構體有中有一個或多個成員。type語句設定了結構體的名稱。結構體的格式如下:

type struct_variable_type struct {   member definition;   member definition;   ...   member definition;}

結構體類型用於變數聲明的文法格式如下:
variable_name := structure_variable_type {value1, value2...valuen}
二叉樹節點的資料結構定義如下:

package mainimport "fmt"type TreeNode struct{   Value int   Left,Right *TreeNode}func main() {   var root TreeNode   fmt.Println(root)}
2、結構體成員的訪問

如果要訪問結構體成員,需要使用點號(.)操作符,格式為:"結構體.成員名"。
結構體類型變數使用struct關鍵字定義,執行個體如下:

func main() {   var root TreeNode   root.Value = 0   root.Left = &TreeNode{Value:1}   root.Right = &TreeNode{2,nil,nil}   root.Left.Left = &TreeNode{Value:3}   root.Print()}
3、結構體方法的定義

結構體方法定義在結構體範圍外,需要在函式宣告中指定接收者。

func (variable_name struct_variable_type) function_name(parameters){    //函數體}

如二叉樹節點的遍曆列印函數如下:

func (node TreeNode) Print(){      fmt.Println(node.Value, " ")}func (node *TreeNode)traverse(){   if node != nil{      //遞迴遍曆左子樹      node.Left.traverse()      node.Print()      //遞迴遍曆右子樹      node.Right.traverse()   }}
4、結構體指標

如果結構體的方法中需要對結構體成員的值進行修改,必須使用結構體指標作為方法的接收者。如果結構體過大也要考慮使用結構體指標作為方法的接收者。值接收者和指標接收者都可以接收值、指標傳遞的結構體。
nil指標也可以調用方法。

package mainimport (   "fmt")type TreeNode struct{   Value int   Left,Right *TreeNode}func createTreeNode(value int) *TreeNode{   return &TreeNode{Value:value}}func (node TreeNode) Print(){      fmt.Println(node.Value, " ")}func (node *TreeNode)traverse(){   if node != nil{      //遞迴遍曆左子樹      node.Left.traverse()      node.Print()      //遞迴遍曆右子樹      node.Right.traverse()   }}func (node *TreeNode)setValue(value int){   if node!= nil{      node.Value = value   }else {      fmt.Println("The node is nil.")   }}func main() {   var root TreeNode   root.Value = 0   root.Left = &TreeNode{Value:1}   root.Right = &TreeNode{2,nil,nil}   root.Left.Left = &TreeNode{Value:3}   root.traverse()   root.setValue(100)   root.traverse()   }
二、包和封裝1、包簡介

包用於組織Go原始碼,提供了更好的可重用性與可讀性。由於包提供了代碼的封裝,因此使得Go應用程式易於維護。
Go語言的物件導向只支援封裝,不支援繼承和多態。
Go語言使用CamelCase命名方法對函數進行命名,函數名稱的首字母大寫表示public,小寫表示private。
存取權限是針對包的,Go語言中每個目錄是一個包,包名與目錄名可以不相同。如果目錄下有一個main函數,目錄只能有一個main包,main包包含可執行入口。
為結構體定義的方法必須在一個包內,但可以是不同的檔案。

2、包的定義

所有可執行檔Go程式都必須包含一個main函數,作為程式啟動並執行入口。main函數應該放置於main包中。
包的定義文法如下:
package packagename
指定某一源檔案屬於一個包,應該放在每一個源檔案的第一行。
匯入一個已存在的包的文法如下:
import "packagename"?
屬於某一個包的源檔案都應該放置於一個單獨命名的檔案夾裡。按照Go語言的慣例,應該用包名命名包的檔案夾。
在packagename檔案夾中,所有檔案都會以package packagename作為開頭,因為檔案夾中所有檔案Go語言檔案都屬於packagename包。

3、包的匯入

為了使用自訂包,必須要先匯入包。匯入自訂包的文法為import path。必須指定自訂包相對於工作區內?src?檔案夾的相對路徑。
Go語言中匯入了包,卻不在代碼中使用包,是非法的。在程式開發階段,常常會先匯入包,而暫不使用,可以使用空白標識符?
var
= packagename.method代碼可以屏蔽錯誤。
如果匯入一個包,只為了確保包進行了初始化,而無需使用包中的任何函數或變數,如需要確保調用包的init函數,而不需要在代碼中使用包,可以使用空白標識符。
import (_ "packagename")
在使用import匯入包的時候,如果發生包命名衝突,可以在import的名稱前面加一個包的別名處理。使用方法如下:
import (packageAnotherName "packagename")

4、init函數

所有包都可以包含一個init函數。init函數不應該有任何傳回值類型和參數,在使用者代碼中也不能顯式地調用。init函數的形式如下:
func init() { }
init函數可用於執行初始化任務,也可用於在開始執行前驗證程式的正確性。
包的初始化順序如下:
A、首先初始化包層級(Package Level)的變數
B、緊接著調用init函數。包可以有多個init函數(在一個檔案或分佈於多個檔案中),按照編譯器解析的順序進行調用。
C、如果一個包匯入另一個包,會最先初始化被匯入的包。
D、一個包可以被匯入多次,但只會被初始化一次。
main包的初始化順序為:
A、首先初始化被匯入的包。
B、接著初始化包層級的變數。
C、調用main包的init函數。
D、最後調用main函數。

三、擴充已有類型

Go語言中使用定義別名和組合來擴充已有的類型。

1、使用組合擴充

可以通過定義一個新的類型,內部組合了要擴充類型的對象對已有類型進行擴充。如對TreeNode類型進行擴充,增加一個後序遍曆的方法。

//使用組合擴充TreeNode類型type BinTreeNode struct{   node *TreeNode}//BinTreeNode的方法func (binTreeNode *BinTreeNode)postOrderTraverse(){   if binTreeNode != nil && binTreeNode.node != nil{      left := BinTreeNode{binTreeNode.node.Right}      left.postOrderTraverse()      right := BinTreeNode{binTreeNode.node.Left}      right.postOrderTraverse()      node := binTreeNode.node      node.Print()   }}
2、使用別名擴充

可以對已有類型定義一個別名,通過對別名資料型別增加新的方法實現對已有類型的擴充。

//定義TreeNode的別名type PreOrderTreeNode TreeNode//定義PreOrderTreeNode類型的方法func (pNode *PreOrderTreeNode)preOrderTraverse(){   if pNode != nil{      node := (*TreeNode)(pNode)      node.Print()      //列印左子樹      left := (*PreOrderTreeNode)(pNode.Left)      left.preOrderTraverse()      //列印右子樹      right := (*PreOrderTreeNode)(pNode.Right)      right.preOrderTraverse()   }}
3、程式執行個體
package mainimport (   "fmt")type TreeNode struct{   Value int   Left,Right *TreeNode}func createTreeNode(value int) *TreeNode{   return &TreeNode{Value:value}}func (node TreeNode) Print(){      fmt.Println(node.Value, " ")}func (node *TreeNode)traverse(){   if node != nil{      //遞迴遍曆左子樹      node.Left.traverse()      node.Print()      //遞迴遍曆右子樹      node.Right.traverse()   }}func (node *TreeNode)setValue(value int){   if node!= nil{      node.Value = value   }else {      fmt.Println("The node is nil.")   }}//使用組合擴充TreeNode類型type PostOderTreeNode struct{   node *TreeNode}//BinTreeNode的方法func (binTreeNode *PostOderTreeNode)postOrderTraverse(){   if binTreeNode != nil && binTreeNode.node != nil{      left := PostOderTreeNode{binTreeNode.node.Right}      left.postOrderTraverse()      right := PostOderTreeNode{binTreeNode.node.Left}      right.postOrderTraverse()      node := binTreeNode.node      node.Print()   }}//定義TreeNode的別名type PreOrderTreeNode TreeNode//定義PreOrderTreeNode類型的方法func (pNode *PreOrderTreeNode)preOrderTraverse(){   if pNode != nil{      node := (*TreeNode)(pNode)      node.Print()      //列印左子樹      left := (*PreOrderTreeNode)(pNode.Left)      left.preOrderTraverse()      //列印右子樹      right := (*PreOrderTreeNode)(pNode.Right)      right.preOrderTraverse()   }}func main() {   var root TreeNode   root.Value = 0   root.Left = &TreeNode{Value:1}   root.Right = &TreeNode{2,nil,nil}   root.Left.Left = &TreeNode{Value:3}   root.traverse()   root.setValue(100)   root.traverse()   fmt.Println()   rootItem1 := PostOderTreeNode{&root}   rootItem1.postOrderTraverse()   fmt.Println()   rootItem2 := (PreOrderTreeNode)(root)   rootItem2.preOrderTraverse()}
四、GO環境變數1、GOROOT

GOROOT環境變數是go的安裝路徑。

GOROOT=/usr/local/goexport GOROOT

要執行go命令和go工具, 需要配置go的可執行檔的路徑:
export $PATH:$GOROOT/bin
如果是windows需要使用;符號分割兩個路徑, mac和類unix使用:符號分割。

2、GOPATH

go install/go get和 go的工具等會用到GOPATH環境變數。
GOPATH是Go語言開發的工作空間,作為編譯後二進位的存放目的地和import包時的搜尋路徑。
GOPATH表示程式碼封裝所在的地址,可以設定多個。
GOPATH環境變數預設在目前使用者主目錄下的go目錄,所有項目和第三方庫都放在同一個GOPATH下。
GOPATH用來存放Go源碼,Go的可運行檔案,以及相應的編譯之後的包檔案。所以這個目錄下面有三個子目錄:src、bin、pkg
GOPATH允許多個目錄,當有多個目錄時,請注意分隔字元,多個目錄的時候Windows是分號,Linux系統是冒號,當有多個GOPATH時,預設會將?go get?的內容放在第一個目錄下。
$GOPATH?目錄約定有三個子目錄:
A、src目錄存放原始碼(比如:.go .c .h .s等)
B、pkg目錄存放編譯後產生的package(比如:.a)
C、bin目錄存放編譯後產生的可執行檔
不能把GOPATH設定成go的安裝路徑,可以自己在使用者目錄下建立一個目錄, 如go。

GOPATH=/home/user/go:/home/user/devexport GOPATH

為了使用方便,通常需要將所有工作空間的bin路徑添加到PATH環境變數中,如:
export $PATH:$GOPATH/bin
如果$GOPATH有多個工作目錄,使用?${GOPATH//://bin:}/bin?添加所有的bin目錄。
export $PATH:${GOPATH//://bin:}/bin
GOPATH有兩個目錄(一個用於存放第三方包,一個使用者開發),如果使用?go工具進行第三方包的安裝,預設會安裝到第一個目錄 (/home/user/go),如果在/home/user/dev中寫代碼,使用g工具(go install,?go build) 會將二進位包安裝到/home/user/dev中。
GOPATH設定兩個目錄的優點在於第一個目錄作為第三方包的存放位置,第二個目錄作為開發人員自己的工作空間。第三方的GOPATH放置到第一位,go 安裝工具會將其作為預設的位置。
當使用go命令搜尋包時,首先搜尋?$GOROOT路徑,然後是$GOPATH/src路徑。

3、遠程包

go語言有一個擷取遠程包的工具就是go get,目前go get支援多數開源社區(例如:github、googlecode、bitbucket、Launchpad)。
go get github.com/xxx/xxx
go get -u 參數可以自動更新包,而且當go get的時候會自動擷取該包依賴的其它第三方包,預設會安裝到$GOPATH的第一個目錄。
在代碼中使用遠程包與使用當地套件一樣。
import?"github.com/xxx/xxx"

Go語言開發(四)、Go語言物件導向

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.