Golang - 結構體
結構體說明
結構體(struct) 是使用者自定義的型別,它代表若干欄位(基本資料型別/引用資料型別)的集合。有些時候將多個數據看做一個整體要比單獨使用這些資料更有意義,這種情況下就適合結構體。
比如將一個員工的name,department,salary三個屬性打包在一起成為一個employee
結構就很有意義的。
結構體型別
結構體是複合型別(composite types),當宣告一個結構體變數的時候,記憶體空間就已經被分配,每個欄位(field)
為型別的0
值。
上面的記憶體示意圖表明瞭,變數employee
宣告為Employee
結構體型別的時候,會初始化該結構體中欄位型別的0
結構體
是值
型別。
不同的結構體型別變數欄位是獨立的,互不影響,一個結構體變數欄位的更改,不影響另外一個結構體型別變數。
package main import "fmt" type Employee struct { Name,Department string Salary float32 Task []string } func main() { var employee1 = Employee{ Name: "易文傑", Department: "系統開發部", Salary: 5000, Task: []string{ "支付", "客戶分配", }, } employee2 := employee1 employee2.Name = "張衝" fmt.Println(employee1,employee2) }
上面的程式碼,聲明瞭一個employee1
變數後,將employee1
賦值給employee2
變數,當我們修改employee2
的欄位Name
後,發現emloyee1
中的Name
並沒有被更改。程式的輸出結果:
{易文傑 系統開發部 5000 [支付 客戶分配]} {張衝 系統開發部 5000 [支付 客戶分配]}
結構體的宣告
type Employee struct {
Name string
Department string
Salary float32
}
上面的程式碼聲明瞭一個名為Employee
的結構體型別,它擁有Name
,Department
,Salary
三個欄位。同一個型別的多個欄位可以合併到一行(用逗號進行分隔),並將型別放到後面。上面的結構體中Name
Department
都是string
的型別,因此可以將它們寫到一起。
type Employee struct {
Name,Department string
Salary float32
}
上面結構體Employee
是一個具名結構體(named structure),因為它建立了一個具有名稱的結構體型別:Employee
。我們可以定義具名結構體型別的變數。
我們也可以定義一個沒有型別名稱的結構體,這種結構體叫做匿名結構體(anonymous structures)
var employee struct{
Name,Department string
Salary float32
}
當結構體中的欄位是map
,slice
,指標
的時候,預設的0
值是nil
(沒有分配空間)的時候,需要分配空間後才能被使用
package main
import "fmt"
type Employee struct {
Name,Department string
Salary float32
Mapper map[string]string
Slicer []string
Ptr *int
}
func main() {
var employee Employee
employee.Name = "易文傑"
employee.Department = "系統開發部"
employee.Mapper = make(map[string]string)
employee.Mapper["smile"] = "易文傑"
employee.Slicer = make([]string,10)
employee.Slicer[0] = "切片"
age := 12
employee.Ptr = &age
fmt.Println(employee)
}
當未分配空間就直接使用,會導致程式碼異常
panic: assignment to entry in nil map
上面的程式會輸出:
{易文傑 系統開發部 0 map[smile:易文傑] [切片 ] 0xc00000a098}
結構體的作用域
結構體採用首字母大小寫來區分訪問許可權,當首字母是大寫,可以別外包引用。反之,不能。
定義具名結構體變數
下面的程式說明了如何定義一個具名結構體Employee
的變數
package main
import "fmt"
//定義結構體
type Employee struct {
Name,Department string
Salary float32
}
func main() {
//使用結構體一
employee1 := Employee{
Name: "易文傑",
Department: "系統研發部",
Salary: 5000,
}
//使用結構體二
employee2 := Employee{"張衝","系統研發部",15000}
fmt.Println(employee1,employee2)
}
在上面的程式中,我們定義了一個名叫Employee
的結構體型別,我們可以通過指定欄位的名稱和對應的值來建立一個結構體變數。其中欄位名和型別必須要和結構體中宣告的保持一致。
採用第一種定義結構體變數:不需
要和宣告結構體中的變數順序保持一致,但最後一個數據需保留,
採用第二種定義結構體變數:需要
和宣告結構體中的變數順序保持一致,最後一個數據不需要保留,
上面的程式輸出如下:
{易文傑 系統研發部 5000} {張衝 系統研發部 15000}
定義匿名結構體變數
package main
import "fmt"
func main() {
var employee = struct {
Name,Department string
Salary float32
}{"張衝","系統開發部",28000}
fmt.Println(employee)
}
在上面的程式中,我們定義了一個employee
匿名結構體變數。這種結構體稱為匿名結構體,因為它只建立了一個新的結構體變數employee
,而沒有定義新的結構體型別。
上面的程式輸出為:
{張衝 系統開發部 28000}
訪問結構體中的欄位
使用.
操作符來訪問結構體中的欄位
package main
import "fmt"
func main() {
var employee = struct {
Name,Department string
Salary float32
}{"張衝","系統開發部",28000}
fmt.Printf("姓名%v\n部門%v\n工資%v\n",employee.Name,employee.Department,employee.Salary)
}
在上面的程式中,通過employee.Name
來訪問employee
中的欄位Name
。程式的輸出為:
姓名張衝
部門系統開發部
工資28000
結構體指標
可以定義指向結構體的指標。
package main
import "fmt"
type Employee struct {
Name,Department string
Salary float32
}
func main() {
//方式一
var employee1 = &Employee{
Name: "張衝",
Department: "系統研發部",
Salary: 18000,
}
//方式二
var employee2 = new(Employee)
employee2.Name = "易文傑"
fmt.Println(employee1.Name)
fmt.Println((*employee1).Name)
fmt.Println(employee2.Name)
fmt.Println((*employee2).Name)
}
上面的程式中,employee1
和employee2
是一個指向Employee
結構體的指標。(*employee1).Name
是訪問employee1
中的Name
欄位。程式的輸出為:
張衝
張衝
易文傑
易文傑
在Go中我們可以使用employee.Name
替代顯示解引用(*employee).Name
來訪問Name
欄位。