1. 程式人生 > 其它 >Golang - 結構體

Golang - 結構體

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
}

當結構體中的欄位是mapslice,指標的時候,預設的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)
}

上面的程式中,employee1employee2是一個指向Employee結構體的指標。(*employee1).Name是訪問employee1中的Name欄位。程式的輸出為:

張衝
張衝
易文傑
易文傑

在Go中我們可以使用employee.Name替代顯示解引用(*employee).Name來訪問Name欄位。