一應俱全的結構體 -- 就要學習 Go 語言

Go 語言的數組能夠存儲一組相同類型的數據,而結構體能夠將不一樣類型的變量數據組合在一塊兒,每個變量都是結構體的成員。數組

建立並初始化一個結構體

可使用下面的語法建立一個結構體:函數

type StructName struct{
    field1 fieldType1
    field2 fieldType2
}
複製代碼

建立一個含有 firstNamelastNamesalaryfullTime 成員變量的結構體 Employee學習

type Empolyee struct{
	firstName string
	lastName string
	salary int
	fullTime bool
}
複製代碼

相同類型的成員變量能夠放在一行,因此,上面的代碼能夠簡寫成:spa

type Empolyee struct{
	firstName,lastName string
	salary int
	fullTime bool
}
複製代碼

使用類型別名 Employee 建立一個結構體變量 ross.net

var ross Empolyee
ross.firstName = "ross"
ross.lastName = "Bingo"
ross.salary = 1000
ross.fullTime = true
fmt.Println(ross)
複製代碼

輸出:指針

{ross Bingo 1000 true}
複製代碼

上面的代碼建立告終構體變量 ross,併爲每個成員變量賦值。使用.訪問結構體的成員。
還可使用字面量的方式初始化結構體:code

1、方式一
ross := Empolyee{
	"ross",
	"Bingo",
	1000,
	true,
}
輸出:{ross Bingo 1000 true}

2、方式二
ross := Empolyee{
	lastName:"Bingo",
	firstName:"ross",
	salary:1000,
}
輸出:{ross Bingo 1000 false}
複製代碼

方式一,初始化時省略了成員變量名稱,可是必須按順序地將給出全部的成員的值。必須記住全部成員的類型且按順序賦值,這給開發人員帶來了額外的負擔且代碼的維護性差,通常不採用這種方式;
提倡採用方式二,不用關心成員變量的順序,給須要初始化的成員賦值,未賦值的成員默認就是類型對應的零值。注意:方式一和方式二初始化方式不能夠混用cdn

ross := Empolyee{
	firstName:"ross",
	lastName:"Bingo",
	1000,
	fullTime:true,
}
複製代碼

編譯出錯:mixture of field:value and value initializers開發

成員變量的順序對於結構體的同一性很重要,若是將上面的 firstNamelastName 互換順序或者將 fullTimesalary 互換順序,都是在定義一個不一樣的結構體類型get

結構體指針

初始化結構體的時候,能夠聲明一個指向結構體的指針:

ross_pointer := &Empolyee{
	firstName:"ross",
	lastName:"Bingo",
	salary:1000,
	fullTime:true,
}
複製代碼

上面的代碼,建立了一個指向 Empolyee 結構體的指針 ross_pointer。能夠經過指針訪問結構體的成員:

fmt.Println(*ross_pointer)
fmt.Println("firstName:",(*ross_pointer).firstName)
fmt.Println("firstName:",ross_pointer.lastName)
複製代碼

輸出:

{ross Bingo 1000 true}
firstName: ross
firstName: Bingo
複製代碼

ross_pointer 是一個結構體變量,因此 (*ross_pointer).firstNameross_pointer.lastName 都是正確的訪問方式 。

匿名成員

定義結構體時能夠只指定成員類型,不用指定成員名,Go 會自動地將成員類型做爲成員名。這種結構體成員稱爲匿名成員這個結構體成員的類型必須是命名類型或者是指向命名類型的指針。

type Week struct{
	string
	int
	bool
}
func main() {
	week := Week{"Friday",1000,true}
	fmt.Println(week)
}
複製代碼

上面的代碼定義告終構體 Week ,有 stringintbool 三個成員變量,變量名與類型相同。 這種定義方式能夠和指定成員名混合使用,例如:

type Empolyee struct{
	firstName,lastName string
	salary int
	bool
}
複製代碼

結構體嵌套

Go 有結構體嵌套機制,一個結構體能夠做爲另外一個結構體類型的成員。

type Salary struct {
	basic int
	workovertime int
}

type Empolyee struct{
	firstName,lastName string
	salary Salary
	bool
}

func main() {
	ross := Empolyee{
	    firstName:"Ross",
            lastName:"Bingo",
            bool:true,
            salary:Salary{1000,100},
	}
	fmt.Println(ross.salary.basic);
}
複製代碼

咱們新定義告終構體類型 Salary,將 Empolyee 成員類型修改爲結構體類型 Salary。 建立告終構體 ross,想要訪問成員 salary 裏面的成員仍是能夠採用 . 的方式,例如:ross.salary.basic
若是結構體嵌套層數過多時,想要訪問最裏面結構體成員時,採用上面這種訪問方式就會牽扯不少中間變量,形成代碼很臃腫。能夠採用上面的匿名成員方式簡化這種操做。
採用匿名成員方式從新定義結構體類型 Empolyee

type Empolyee struct{
	firstName,lastName string
	Salary    // 匿名成員
	bool
}
func main() {
	ross := Empolyee{
		firstName:"Ross",
		lastName:"Bingo",
		bool:true,
		Salary:Salary{1000,100},
	}
	fmt.Println(ross.basic);         // 訪問方式一
	fmt.Println(ross.Salary.basic);  // 訪問方式二
	ross.basic = 1200
	fmt.Println(ross.basic)          // update
}
複製代碼

上面兩種方式是等價的。經過這種方式,簡化了訪問過程。
須要注意的是,被嵌套的匿名結構體成員中,不能與上一層結構體成員同名。

type Empolyee struct{
	firstName,lastName string
	Salary
	basic int
	bool
}
func main() {
	ross := Empolyee{
		firstName:"Ross",
		lastName:"Bingo",
		bool:true,
		Salary{1000,100},
	}
	fmt.Println(ross.basic)
}
複製代碼

上面的代碼,咱們修改告終構體 Empolyee ,多添加了一個與 Salary.basic 同名的成員,可是編譯出錯: mixture of field:value and value initializers

可導出的成員

一個 Go 包中的變量、函數首字母大寫,那這個變量或函數是能夠導出的。這是 Go 最主要的訪問控制機制。若是一個結構體的成員變量名首字母大寫,那這個成員也是可導出的。一個結構體能夠同時包含可導出和不可導出的成員變量。
在路徑 WORKSPACE/src/org/employee.go 建立一個名爲 org 的包,添加以下代碼:

// employee.go
package org
type Employee struct {
	FirstName,LastName string
	salary int
	fullTime bool
}
複製代碼

上面的 Employee 結構體,只有變量 FirstNameLastName 是可導出的。固然,Employee 也是可導出的。 在 main 包中導入 org 包:

// main.go
package main
import (
	"org"
	"fmt"
)
func main() {
	ross := org.Employee{
		FirstName:"Ross",
		LastName:"Bingo",
		salary:1000,     
	}
	fmt.Println(ross)
}
複製代碼

上面的代碼編譯出錯,由於成員變量 salary 是不可導出的: unknown field 'salary' in struct literal of type org.Employee

由於 Employee 來自包 org,因此用 org.Employee 去建立結構體 ross。能夠採用類型別名簡化:

package main

import (
	"org"
	"fmt"
)

type Employee org.Employee; 

func main() {
	ross := Employee{
		FirstName:"Ross",
		LastName:"Bingo",
	}
	fmt.Println(ross)
}
複製代碼

輸出:

{Ross Bingo 0 false}
複製代碼

結構體比較

若是結構體的全部成員都是可比較的,則這個結構體就是可比較的。可使用 ==!= 做比較,其中 == 是按照順序比較兩個結構體變量的成員變量。

type Employee struct {
	FirstName,LastName string
	salary int
	fullTime bool
}
func main() {
	ross := Employee{
		FirstName:"Ross",
		LastName:"Bingo",
	}
	jack := Employee{
		FirstName:"Jack",
		LastName:"Lee",
	}
	fmt.Println(ross == jack)
}
複製代碼

輸出:

false
複製代碼

不一樣類型的結構體變量是不能比較的:

type User struct {
	username string
}
type Employee struct {
	FirstName,LastName string
	salary int
	fullTime bool
}
func main() {
	ross := Employee{
		FirstName:"Ross",
		LastName:"Bingo",
	}
	user := User{
		username:"Seekload",
	}
	fmt.Println(ross == user)
}
複製代碼

編譯出錯: invalid operation: ross == user (mismatched types Employee and User) .
然而,若是有成員是不能比較的,例如:map,則這個結構體是不能比較的。


(全文完)

原創文章,若需轉載請註明出處!
歡迎掃碼關注公衆號「Golang來啦」或者移步 seekload.net ,查看更多精彩文章。

公衆號「Golang來啦」給你準備了一份神祕學習大禮包,後臺回覆【電子書】領取!

公衆號二維碼
相關文章
相關標籤/搜索