Go 語言的數組能夠存儲一組相同類型的數據,而結構體能夠將不一樣類型的變量數據組合在一塊兒,每個變量都是結構體的成員。數組
可使用下面的語法建立一個結構體:函數
type StructName struct{
field1 fieldType1
field2 fieldType2
}
複製代碼
建立一個含有 firstName
、lastName
、salary
和 fullTime
成員變量的結構體 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
開發
成員變量的順序對於結構體的同一性很重要,若是將上面的 firstName
、lastName
互換順序或者將 fullTime
、salary
互換順序,都是在定義一個不一樣的結構體類型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).firstName
和 ross_pointer.lastName
都是正確的訪問方式 。
定義結構體時能夠只指定成員類型,不用指定成員名,Go 會自動地將成員類型做爲成員名。這種結構體成員稱爲匿名成員。這個結構體成員的類型必須是命名類型或者是指向命名類型的指針。
type Week struct{
string
int
bool
}
func main() {
week := Week{"Friday",1000,true}
fmt.Println(week)
}
複製代碼
上面的代碼定義告終構體 Week
,有 string
、int
和 bool
三個成員變量,變量名與類型相同。 這種定義方式能夠和指定成員名混合使用,例如:
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
結構體,只有變量 FirstName
、LastName
是可導出的。固然,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來啦」給你準備了一份神祕學習大禮包,後臺回覆【電子書】領取!