結構體是一種聚合的自定義數據類型,是由零個或任意多個相同或不一樣類型的變量聚合而成的數據集合,每一個變量稱爲結構體成員(也可稱之爲成員變量,字段,屬性)。bash
使用 type 和 struct 語句定義結構體,type 語句設定告終構體的類型名稱,struct 語句定義一個新的數據類型,結構體中有一個或多個成員。函數
格式以下:佈局
/*
type 類型名 struct {
字段1 字段1類型
字段2 字段2類型
…
字段3 字段3類型
}
*/
type struct_variable_type struct {
member definition;
member definition;
...
member definition;
}
// 或者 同一類型的字段,能夠定義在一行
type Color struct {
R, G, B byte
}
複製代碼
注意:ui
type A struct {
Hour int // 可導出
minute int // 不可導出
}
複製代碼
結構體自己是一種類型,能夠像整型、字符串等類型同樣,以 var 的方式聲明結構體便可完成實例化。spa
structure_variable_type
爲結構體類型,variable_name
爲結構體的實例。指針
// 給 variable_name 分配內存,並零值化內存,可是這個時候的 variable_name 的類型是 structure_variable_type
var variable_name structure_variable_type
複製代碼
使用 new 函數給一個新的結構體變量分配內存,它返回指向已分配內存的指針:var variable_name *structure_variable_type = new(structure_variable_type)
。code
variable_name := new(structure_variable_type)
複製代碼
variable_name := structure_variable_type {value1, value2, valuen3}
或
variable_name := structure_variable_type {key1: value1, key2: value2, key3: value3}
variable_name := &structure_variable_type {value1, value2, valuen3} // 等效於 new(structure_variable_type)
複製代碼
要訪問結構體成員,須要使用點號 . 操做符,格式爲:內存
// 結構體.成員名
type Point struct {
X int
Y int
}
var p Point
p.X = 10
p.Y = 20
複製代碼
若是結構體的全部成員變量均可以比較,那麼這個結構體是能夠比較的。兩個結構體的比較可使用 == 或者 !=。ci
例如:字符串
type C struct {
A int
B string
}
c1 := C{A:1, B:"abc"}
c2 := C{A:1, B:"abc"}
c3 := C{A:2, B:"abc"}
fmt.Println(c1.A == c2.A && c1.B == c2.B) // true
fmt.Println(c1 == c2) // true 與上等價
fmt.Println(c1.A == c3.A && c1.B == c3.B) // false
fmt.Println(c1 == c3) // false 與上等價
複製代碼
和其餘可比較的類型同樣,可比較的結構體類型均可以做爲map的鍵類型。
例如:
type C struct {
A int
B string
}
mp := make(map[C]int)
key := C{A:1, B:"abc"}
mp[key] = 9
fmt.Println(mp[C{A:1, B:"abc"}]) // 9
複製代碼
Go語言容許咱們定義不帶名稱的結構體成員,只須要指定類型便可;這種結構體成員稱做匿名成員。這個結構體成員的類型必須是一個命名類型或者指向命名類型的指針。正是由於有了這種結構體嵌套的功能,咱們才能直接訪問到咱們須要的變量而不是指定一大串中間變量。
type Point struct {
X int
Y int
}
type Circle struct {
Point
}
var c Circle
c.X = 10 // 等價於 c.Point.X = 10
c.Y = 10 // 等價於 c.Point.Y = 10
type Wheel struct {
*Point
}
複製代碼
結構體字面量初始化沒有快捷方式,必須遵循形狀類型的定義。
type Point struct {
X int
Y int
}
type Circle struct {
Point
}
var c Circle
c = Circle{1,1} // 錯誤
c = Circle{Point{1,1}} // 正確
c = Circle{Point: Point{1,1}} // 正確
複製代碼
由於「匿名成員」擁有隱式的名字,因此你不能在一個結構體裏面定義兩個相同類型的匿名成員,不然會引發衝突。因爲匿名成員的名字是由它們的類型決定的,所以它們的可導出性也是由他們的的類型決定。在下面的例子中,point和circle這兩個匿名成員是可導出的,即便這兩個結構體是不可導出的(point和circle)。
type point struct {
X int
Y int
}
type circle struct {
point
}
type Wheel struct {
circle
}
var w Wheel
w.X = 8 // 等價於 w.circle.point.X = 8, w.X是可導出的,w.circle.point.X是不可導出的
複製代碼
能夠像其餘數據類型同樣將結構體類型做爲參數傳遞給函數。並以實例的方式訪問結構體變量。 例如:
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func changeBook(book Books) {
book.title = "book1_change"
fmt.Println(book)
}
func main() {
var book1 Books;
book1.title = "book1"
book1.author = "zuozhe"
book1.book_id = 1
changeBook(book1)
fmt.Println(book1)
}
複製代碼
函數中結構體做爲參數,若是不是用結構指針,函數內參數屬性的改變不影響原來結構體數據。 結果爲:
{book1_change zuozhe 1}
{book1 zuozhe 1}
複製代碼
能夠定義指向結構體的指針相似於其餘指針變量,格式以下:
var struct_pointer *Books
複製代碼
以上定義的指針變量能夠存儲結構體變量的地址。查看結構體變量地址,能夠將 & 符號放置於結構體變量前:
struct_pointer = &Book1
複製代碼
使用結構體指針訪問結構體成員,使用 "." 操做符:
struct_pointer.title
複製代碼