Go 結構體的使用

 

 

 

結構體是用戶定義的類型,表示若干個字段(Field)的集合。有時應該把數據整合在一塊兒,而不是讓這些數據沒有聯繫。這種狀況下可使用結構體。app

例如,一個職員有 firstNamelastName 和 age 三個屬性,而把這些屬性組合在一個結構體 employee 中就很合理。函數

 

結構體的聲明基礎

type Employee struct {
    firstName string
    lastName  string
    age       int
}

 在上面的代碼片斷裏,聲明瞭一個結構體類型 Employee,它有 firstNamelastName 和 age 三個字段。經過把相同類型的字段聲明在同一行,結構體能夠變得更加緊湊。在上面的結構體中,firstName 和 lastName 屬於相同的 string 類型,因而這個結構體能夠重寫爲: spa

type Employee struct {
    firstName, lastName string
    age, salary         int
}

上面的結構體 Employee 稱爲 命名的結構體(Named Structure)。咱們建立了名爲 Employee 的新類型,而它能夠用於建立 Employee 類型的結構體變量。操作系統

聲明結構體時也能夠不用聲明一個新類型,這樣的結構體類型稱爲 匿名結構體(Anonymous Structure)。指針

var employee struct {
    firstName, lastName string
    age int
}

上述代碼片斷建立一個匿名結構體 employee 。  code

  emp3 := struct {
        firstName, lastName string
        age, salary         int
    }{
        firstName: "Andreah",
        lastName:  "Nikola",
        age:       31,
        salary:    5000,
    }

 上述代碼片斷經過匿名結構體 建立了一個結構體變量 。 對象

 

結構體基礎使用

  • 結構體變量初始化
  • 結構體指針變量初始化
  • 結構體變量之間的比較與賦值
  • 在函數中傳遞結構體變量與結構體指針變量
  • 定義結構體函數成員與調用
package main

import (
	"fmt"
)
//結構體爲類型定義
//建立一個結構體,四個數據屬性,四個函數屬性
/////////////////////////////////////
type Person struct {
		name string
		age int
		sex bool
		//hobby []string
}

//*Person意味傳遞是真實地址
func (p *Person)Eat(){
	fmt.Printf("%s愛吃西紅柿炒雞蛋\n",p.name)
}
func (p *Person)Drink(){
	fmt.Printf("%s愛喝可樂\n",p.name)
}
func (p *Person)Sleep(){
	fmt.Printf("%s要睡8個小時\n",p.name)
}
func (p *Person)Love(){
	fmt.Printf("%s喜歡\n",p.name)
}
////////////////////////////////////////////

//值傳遞與屬性傳遞
////////////////////////
func MakeHimLove(p Person){p.Love()}

func MakeHisPtrLove(p *Person){p.Love()}
/////////////////////

func main(){


//////結構體變量初始化///////////////
	//順序初始化:建立對象時按順序給全部屬性賦值
	p1 := Person{"lili",8,true}
	fmt.Println(p1)
	//指定成員初始化:指定成員變量進行賦值,沒有指定的成員變量爲默認值
	p2 := Person{name:"mingming",sex:true} //--未初始化的成員變量,取該數據類型的默認值。
	fmt.Println(p2)
	//建立後初始化:
	p3 := Person{} //--未初始化的成員變量,取該數據類型的默認值。
	p3.name ="xiaoli"
	p3.age =19
	fmt.Println(p3)
////////////////////////


///////////結構體指針變量初始化/////////////

	//通常初始化
	var p4 *Person = &Person{"weiai",26,true}
	fmt.Println(p4)

	//使用new初始化
	p5 := new(Person)
	p5.name ="titi"
	p5.age =31
	p5.sex =false
	//注意:在64位操做系統下,全部類型的指針,均爲8個字節
////////////////////////

///////////結構體變量的比較和賦值/////////////
//1.比較:只能使用 ==和!=   不能使用 > < >=  <=
//注意:結構體有些類型存在,結構體變量是不能進行比較的,如:[]string
//結構體是值類型。若是它的每個字段都是可比較的,則該結構體也是可比較的。若是兩個結構體變量的對應字段相等,則這兩個變量也是相等的。 fmt.Println("p1 == p2:",p1 == p2) //2.賦值:相同類型結構體能夠直接賦值 var temp Person temp = p1 fmt.Println(temp) //////////////////////// ////////////函數內部使用結構體傳參///////////// //值傳遞傳遞的是副本,引用傳遞傳遞的纔是自己 //注意:值傳遞內存消耗大,效率低 //unasfe.Sizeof(變量名):查看變量所佔的內存空間大小 //要求傳遞值就必須傳遞值 //MakeHimLove(p1) //要求傳遞指針就必須傳遞指針:地址傳遞、引用傳遞 //結構體變量的地址爲結構體首個元素的地址 //MakeHisPtrLove(&p1) ///////////////////// ////////////結構體調用自身函數////////////////// ///////////////////// // //實例調用方法 // p1.Eat() // p1.Drink() // p1.Sleep() // p1.Love() ///////////////////////////////////////////// }

  

  

補充知識點

  • 匿名字段
  • 嵌套結構體(Nested Structs)
  • 提高字段(Promoted Fields)
  • 導出結構體和字段blog

匿名字段

當咱們建立結構體時,字段能夠只有類型,而沒有字段名。這樣的字段稱爲匿名字段(Anonymous Field)。教程

如下代碼中有 Person 結構體,它含有兩個匿名字段 string 和 int內存

package main

import (  
    "fmt"
)
type Person struct {  
    string
    int
}

func main() {  
    p := Person{"Naveen", 50}
    fmt.Println(p)
}

該程序輸出 {Naveen 50}

雖然匿名字段沒有名稱,但其實匿名字段的名稱就默認爲它的類型。好比在上面的 Person 結構體裏,雖然說字段是匿名的,但 Go 默認這些字段名是它們各自的類型。因此 Person 結構體有兩個名爲 string 和 int 的字段。

 

嵌套結構體(Nested Structs)

結構體的字段有可能也是一個結構體。這樣的結構體稱爲嵌套結構體。

package main

import (  
    "fmt"
)

type Address struct {  
    city, state string
}
type Person struct {  
    name string
    age int
    address Address
}

func main() {  
    var p Person
    p.name = "Naveen"
    p.age = 50
    p.address = Address {
        city: "Chicago",
        state: "Illinois",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:",p.age)
    fmt.Println("City:",p.address.city)
    fmt.Println("State:",p.address.state)
}

上面的結構體 Person 有一個字段 address,而 address 也是結構體。該程序輸出:

Name: Naveen  
Age: 50  
City: Chicago  
State: Illinois
 

  

 

提高字段(Promoted Fields)

若是是結構體中有匿名的結構體類型字段,則該匿名結構體裏的字段就稱爲提高字段。這是由於提高字段就像是屬於外部結構體同樣,能夠用外部結構體直接訪問。我知道這種定義很複雜,因此咱們直接研究下代碼來理解吧。

type Address struct {  
    city, state string
}
type Person struct {  
    name string
    age  int
    Address
}

在上面的代碼片斷中,Person 結構體有一個匿名字段 Address,而 Address 是一個結構體。如今結構體 Address 有 city 和 state 兩個字段,訪問這兩個字段就像在 Person 裏直接聲明的同樣,所以咱們稱之爲提高字段。

package main

import (
    "fmt"
)

type Address struct {
    city, state string
}
type Person struct {
    name string
    age  int
    Address
}

func main() {  
    var p Person
    p.name = "Naveen"
    p.age = 50
    p.Address = Address{
        city:  "Chicago",
        state: "Illinois",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:", p.age)
    fmt.Println("City:", p.city) //city is promoted field
    fmt.Println("State:", p.state) //state is promoted field
}

在上面代碼中的第 26 行和第 27 行,咱們使用了語法 p.city 和 p.state,訪問提高字段 city 和 state 就像它們是在結構體 p 中聲明的同樣。該程序會輸出:

Name: Naveen  
Age: 50  
City: Chicago  
State: Illinois

  

導出結構體和字段

若是結構體名稱以大寫字母開頭,則它是其餘包能夠訪問的導出類型(Exported Type)。一樣,若是結構體裏的字段首字母大寫,它也能被其餘包訪問到。

讓咱們使用自定義包,編寫一個程序來更好地去理解它。

在你的 Go 工做區的 src 目錄中,建立一個名爲 structs 的文件夾。另外在 structs 中再建立一個目錄 computer

在 computer 目錄中,在名爲 spec.go 的文件中保存下面的程序。

package computer

type Spec struct { //exported struct  
    Maker string //exported field
    model string //unexported field
    Price int //exported field
} 

上面的代碼片斷中,建立了一個 computer 包,裏面有一個導出結構體類型 SpecSpec 有兩個導出字段 Maker 和 Price,和一個未導出的字段 model。接下來咱們會在 main 包中導入這個包,並使用 Spec 結構體。

package main

import "structs/computer"  
import "fmt"

func main() {  
    var spec computer.Spec
    spec.Maker = "apple"
    spec.Price = 50000
    fmt.Println("Spec:", spec)
}

包結構以下所示:

src  
   structs
        computer
            spec.go
        main.go

在上述程序的第 3 行,咱們導入了 computer 包。在第 8 行和第 9 行,咱們訪問告終構體 Spec 的兩個導出字段 Maker 和 Price。執行命令 go install structs 和 workspacepath/bin/structs,運行該程序。

若是咱們試圖訪問未導出的字段 model,編譯器會報錯。將 main.go 的內容替換爲下面的代碼。

package main

import "structs/computer"  
import "fmt"

func main() {  
    var spec computer.Spec
    spec.Maker = "apple"
    spec.Price = 50000
    spec.model = "Mac Mini"
    fmt.Println("Spec:", spec)
}

在上面程序的第 10 行,咱們試圖訪問未導出的字段 model。若是運行這個程序,編譯器會產生錯誤:spec.model undefined (cannot refer to unexported field or method model)

refer:『GCTT 出品』Go 系列教程 —— 第 16 部分:結構體

相關文章
相關標籤/搜索