兄弟連Go語言培訓分享Struct結構體

來源:互聯網
上載者:User

兄弟連Go語言培訓課程體系設計架構包括了區塊鏈的基礎語言Go語言、區塊鏈後端技術體系、區塊鏈公鏈、區塊鏈分布式應用開發等內容講解,以及到最後的面試指導和項目實戰。課程由清華微軟Google名師團隊精心打造,曆時半年時間共同研發而出。

  先介紹一下go語言的類型系統


  Golang中的類型系統


  類型系統是指一個語言的類型體繫結構。一個典型的類型系統通常包含如下基本內容:


  q基礎類型,如byte、int、bool、float等;


  q複合類型,如數組、結構體、指標等;


  q可以指向任意對象的類型(Any類型);


  q值語義和引用語義;


  q物件導向,即所有具備物件導向特徵(比如成員方法)的類型;


  q介面。


  Go語言中的大多數類型都是值語義,並且都可以包含對應的操作方法。在需要的時候,你可以給任何類型(包括內建類型)“增加”新方法。而在實現某個介面時,無需從該介面繼承(事實上,Go語言根本就不支援物件導向思想中的繼承文法),只需要實現該介面要求的所有方法即可。任何類型都可以被Any類型引用。Any類型就是空介面,即interface{}。


  什麼是結構體


  結構體(struct)是使用者自訂的類型,它代表若干欄位的集合,可以用於描述一個實體物件,類似java中的class,是golang物件導向編程的基礎類型。


  結構體的概念在軟體工程上舊的術語叫ADT(抽象資料類型:AbstractDataType)。在C++它也存在,並且名字也是struct,在物件導向的程式設計語言中,跟一個無方法的輕量級類一樣。因為Go語言中沒有類的概念,所以在Go中結構體有著更為重要的地位。


  如何定義一個結構體


  typeCoordinatestruct{


  X,Yfloat32


  }


  文法:typestruct{}


  上述代碼定義個一個名為Coordinate的結構體,裡麵包括了兩個float32的變數X,Y,該結構體可用於表示一個平面座標。


  添加對象方法


  其他的經典物件導向語言,如java,C#,定義對象方法時,會包含在class的定義內,如


  publicclassCoordinate{


  publicfloatX{get;set;}


  publicfloatY{get;set;}


  //列印座標


  publicvoidGetCoordinate(){


  Console.WriteLine("("+this.X+","+this.Y+")");


  }


  }


  在go語言中,對象方法在結構體定義的外部添加


  typeCoordinatestruct{


  X,Yfloat32


  }


  //列印座標


  func(coo*Coordinate)GetCoordinate(){


  fmt.Printf("(%.2f,%.2f)\n",coo.X,coo.Y)


  return


  }


  其中,func關鍵字後面的(coo*Coordinate),表示該函數傳入一個指向Coordinate的指標,可通過指標變數coo來操作結構體的值。


  幾種結構體初始化


  一、按原始欄位順序通過建立結構體


  packagemain


  import(


  "fmt"


  )


  funcmain(){


  p0:=Coordinate{1,2}


  p0.GetCoordinate()


  }


  輸出:(1.00,2.00),其中X=1,Y=2


  二、按照自訂欄位順序進行初始化


  packagemain


  import(


  "fmt"


  )


  funcmain(){


  p0:=Coordinate{Y:1,X:2}


  p0.GetCoordinate()


  }


  輸出:(2.00,1.00),其中X=2,Y=1


  三、通過new函數建立


  packagemain


  import(


  "fmt"


  )


  funcmain(){


  //給該結構體p2變數分配記憶體,它返回指向已指派記憶體的指標


  p0:=new(Coordinate)


  p0.X=1


  p0.Y=2


  p0.GetCoordinate()


  }


  輸出:(1.00,2.00),其中X=1,Y=2


  其中p0:=new(Coordinate)等價於以下寫法


  p3:=&Coordinate{X:1,Y:2}


  p3:=&Coordinate{1,2}


  比較三種建立方式


  其中,第一種與第二種,p0均為一個類型為Coordinate的執行個體,而第三種p0為一個指向Coordinate的指標,相當於varp0*Coordinate=new(Coordinate)


  一般在進行例如typeTstruct{a,bint}的結構體定義之後


  習慣使用t:=new(T)給該結構體變數分配記憶體,它返回指向已指派記憶體的指標。變數t是一個指向T的指標,此時結構體欄位的值是它們所屬類型的零值。


  聲明vartT也會給t分配記憶體,並零值化記憶體,但是這個時候t是類型T。在這兩種方式中,t通常被稱做類型T的一個執行個體(instance)或對象(Object)。vart*T=new(T)等價於t:=new(T)。


  通過程式碼分析以上結論


  packagemain


  import(


  "fmt"


  )


  funcmain(){


  p0:=Coordinate{1,2}


  //給該結構體p2變數分配記憶體,它返回指向已指派記憶體的指標


  p2:=new(Coordinate)


  p2.X=1


  p2.Y=2


  p3:=&Coordinate{X:1,Y:2}


  p4:=&Coordinate{1,2}


  fmt.Println("-------輸出p0-------")


  fmt.Printf("%v\n%T\n",p0,p0)


  fmt.Println("-------輸出p2-------")


  fmt.Printf("%v\n%T\n",p2,p2)


  fmt.Println("-------輸出p3-------")


  fmt.Printf("%v\n%T\n",p3,p3)


  fmt.Println("-------輸出p4-------")


  fmt.Printf("%v\n%T\n",p4,p4)


  }


  輸出:


  -------輸出p0-------


  {12}


  Coordinate


  -------輸出p2-------


  &{12}


  *Coordinate


  -------輸出p3-------


  &{12}


  *Coordinate


  -------輸出p4-------


  &{12}


  *Coordinate


  可以看出來,p2,p3,p4均為一個指標變數


  添加值拷貝的對象方法


  剛才說到了,添加一個對象方法,可以通過func(t*T)functionname()來建立,其中t為一個指標變數。我們也可以通過值拷貝的方式,添加一個對象方法,文法為func(tT)functionname()


  packagemain


  import(


  "fmt"


  )


  typeCoordinatestruct{


  X,Yfloat32


  }


  func(coo*Coordinate)GetCoordinate(){


  fmt.Printf("(%.2f,%.2f)\n",coo.X,coo.Y)


  return


  }


  //值拷貝對象方法


  func(cooCoordinate)SetPosition01(afloat32,bfloat32){


  coo.X=a


  coo.Y=b


  }


  //指標變數對象方法


  func(coo*Coordinate)SetPosition02(afloat32,bfloat32){


  coo.X=a


  coo.Y=b


  }


  funcmain(){


  p0:=Coordinate{1,2}


  fmt.Print("SetPosition02調用前:")


  p0.GetCoordinate()


  p0.SetPosition02(0,0)


  fmt.Print("SetPosition02調用後:")


  p0.GetCoordinate()


  }


  輸出:


  SetPosition01調用前:(1.00,2.00)


  SetPosition01調用後:(1.00,2.00)


  SetPosition02調用前:(1.00,2.00)


  SetPosition02調用後:(0.00,0.00)


  從程式輸出中可以看出,調用SetPosition01方法,發生了值拷貝,即使在方法內改變了coo的值,外部的p0的值沒有被改變。而SetPosition02方法中,coo為指向p0地址的指標,由於是通過指標變數修改了X,Y的值,所以調用完畢後,外部p0的值會被修改為(0,0)


  匿名結構體


  packagemain


  import(


  "fmt"


  )


  funcmain(){


  p_3d:=struct{


  X,Y,Zfloat32


  }{1,2,3}


  fmt.Println("-------輸出p_3d-------")


  fmt.Printf("%v\n%T\n",p_3d,p_3d)


  }


  輸出:


  -------輸出p_3d-------


  {123}


  struct{Xfloat32;Yfloat32;Zfloat32}


  p_3d為一個包含X,Y,Z三個變數的匿名結構體


  golang建構函式?


  在Go語言中沒有建構函式的概念,對象的建立通常交由一個全域的建立函數來完成,以NewXXX來命名,表示“建構函式”:


  這一切非常自然,開發人員也不需要分析在使用了new之後到底背後發生了多少事情。在Go語言中,一切要發生的事情都直接可以看到。


  funcNewRect(x,y,width,heightfloat64)*Rect{


  return&Rect{x,y,width,height}


  }


  變數、方法可見度


  Go語言對關鍵字的增加非常吝嗇,其中沒有private、protected、public這樣的關鍵字。要使某個符號對其他包(package)可見(即可以訪問),需要將該符號定義為以大寫字母開頭,如:


  typeRectstruct{


  X,Yfloat64


  Width,Heightfloat64


  }


  這樣,Rect類型的成員變數就全部被匯出了,可以被所有其他引用了Rect所在包的代碼訪問到。成員方法的可訪問性遵循同樣的規則,例如:


  func(r*Rect)area()float64{


  returnr.Width*r.Height


  }


  這樣,Rect的area()方法只能在該類型所在的包內使用。


  需要注意的一點是,Go語言中符號的可訪問性是包一級的而不是類型一級的。在上面的例子中,儘管area()是Rect的內部方法,但同一個包中的其他類型也都可以訪問到它。這樣的可訪問性控制很粗曠,很特別,但是非常實用。如果Go語言符號的可訪問性是類型一級的,少不了還要加上friend這樣的關鍵字,以表示兩個類是朋友關係,可以訪問彼此的私人成員。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.