Golang中結構體struct定義,結構體指標,空結構體和nil區別學習
Golang中陣列可以儲存同一型別的資料,但在結構體中我們可以為不同項定義不同的資料型別。
結構體是由一系列具有相同型別或不同型別的資料構成的資料集合。
類似Java,Python中的class。
1.語法
關鍵字struct
表示建立一個結構體,語法如下
type struct_variable_name struct {
member1 definition
member2 definition
...
member definition
}
我們定義一個Person結構體,包含name,age,hight三個成員變數:
type Person struct {
name string
age int
hight float64
}
一旦定義了結構體型別,它就能用於變數的宣告
2.初始化
結構體初始化有多種方式,根據應用場景自由選擇
(1).方式一,簡短宣告初始化:
bob := Person{"Bob", 19, 1.85}
fmt.Printf("Bob 資料型別:%T,值為:%v\n", bob, bob)
輸出為:
Bob 資料型別:main.Person,值為:{Bob 19 1.85}
這個結構體是在main
方法中定義的,為了能夠執行main
方法,匯入包的地方必須寫為:
package main
所以,在輸出 Bob 資料型別的時候,前面有個 main
,.
點表示隸屬於main包下的結構體。 之後輸出的是Bob結構體的內容
(2).方式二,var 定義:
var alan Person
fmt.Println("alan 結構體:", alan)
alan.name = "Alan"
alan.age = 20
alan.hight = 1.78
fmt.Println("Alan 結構體內容:", alan)
輸出為:
alan 結構體: { 0 0} // { 0 0} 注意:第一個值是空字串,控制檯輸出不明顯,看不出來
Alan 結構體內容: {Alan 20 1.78}
通過var
宣告結構體(未初始化)alan,alan是一個只有預設值的結構體,不是nil。
我們可以試驗一下:
var jerry Person
fmt.Printf(jerry == nil) // 這段程式碼編譯會報錯->無效操作:不匹配的型別Person和nil
// 報錯內容:invalid operation: jerry == nil (mismatched types Person and nil)
我們定義了一個名為jerry的結構體,並未進行初始化,在判斷是否為nill時,程式碼報錯了
首先要明白,Golang中nil
表示什麼,以下是我從原始碼中複製的:
// nil is a predeclared identifier representing the zero value for a
// pointer, channel, func, interface, map, or slice type.
var nil Type // Type must be a pointer, channel, func, interface, map, or slice type
可以看到, nil
的型別必須是一個指標,通道,函式,介面,字典,切片型別,他們都是引用型別
而結構體struct
是值型別,jerry結構體未初始化,其成員變數的值都會取預設值,所以也可以理解為是有值,只不過是預設值。
(3).方式三:Person{}
結構體後面加 {},表示宣告結構體。
tom := Person{}
tom.name = "Tom"
tom.age = 21
tom.hight = 1.73
fmt.Println("Tom 結構體內容:", tom)
輸出為:
Tom 結構體內容: {Tom 21 1.73}
(4).方式四:Person{}變體
(3)方式中是先建立一個結構體,然後初始化,分兩步操作的。其實我們可以一步到位的:
jack := Person{
name: "Jack",
age: 19,
hight: 1.69,
}
fmt.Println("Jack 結構體內容:", jack)
輸出:
Jack 結構體內容: {Jack 19 1.69}
它是一個指標,指向了一個結構體
1.結構體前面加’*’
在結構體前面加一個*
即可
var jerryPtr *Person // 定義一個結構體指標,指標指向Person
jerryPtr = &bob // 將bob的記憶體地址賦值給jerryPtr
fmt.Println("jerryPtr 結構體指標為:", jerryPtr)
fmt.Printf("jerryPtr 結構體指標地址為:%p,型別為:%T\n", &jerryPtr, jerryPtr)
輸出:
jerryPtr 結構體指標為: &{Bob 19 1.85}
jerryPtr 結構體指標地址為:0xc000006030,型別為:*main.Person
2.通過new()
建立結構體
或者通過new()
建立結構體,返回的也是一個指標
alan := new(Person)
fmt.Println("alan 為:", alan) // 不是nill
fmt.Printf("alan 的地址為:%p,資料型別為;%T\n", alan, alan)
alan.name = "Alan"
alan.age = 19
alan.hight = 1.79
fmt.Println("alan 結構體的內容為:", alan)
輸出:
alan 為: &{ 0 }
alan 的地址為:0xc00006e540,資料型別為;*main.Person
alan 結構體的內容為: &{Alan 19 男}
觀察輸出,我們發現,alan 的資料型別*main.Person
,是一個指標。
3.空結構體和nil區別
寫到這裡,在思考一個問題,那我定義一個沒有任何成員變數的結構體,new的時候,返回的是不是nil
呢?
檢視了下new()函式返回的是指標型別,原始碼如下:
// The new built-in function allocates memory. The first argument is a type,
// not a value, and the value returned is a pointer to a newly
// allocated zero value of that type.
func new(Type) *Type
帶著疑問,實際操作一下。
我們先定義一個空結構體:
type Student struct {
}
然後我們在main
函式中宣告一個空結構體,並判斷是否為nill
:
student := new(Student)
fmt.Printf("student 的資料型別為:%T,值為:%v\n", student, student)
fmt.Println("student == nill :", student == nil)
輸出:
student 的資料型別為:*main.Student,值為:&{}
student == nill : false
可以看到,空結構體student
並不是nil
,而且其的值為 &{}。
寫到這裡,返回上文看了下nil
的原始碼,疑惑瞬間解開了:
stuct
是一個值型別,即使加了*
也只是變成了一個指標,指向結構體了。nil
是一個Type
,根據原始碼var nil Type
,它其實也是Golang中的一中型別,nil的型別必須是一個指標,通道,函式,介面,字典,切片型別
舉個例子,宣告一個slice
,不做任何初始化,那麼該slice
就是一個nil
Talk is cheap, show me code:
var s []int64
fmt.Println("s :", s)
fmt.Println("s == nil:", s == nil)
輸出:
s : []
s == nil: true
可以看到,s 確實一個nil
,和我們思考的一樣。
總結一下,今天記錄了struct
的定義和宣告方式,弄清楚了空結構體和nil
的區別。
nil
在概念上和其它語言的null、None、nil、NULL一樣,都指代零值或空值。nil
是預先說明的識別符號,也即通常意義上的關鍵字。在Golang中,nil
只能賦值給指標、channel
、func
、interface
、map
或slice
型別的變數
另外,要注意的是,在Golang中struct
是值型別,結構體作為引數時,是副本拷貝。如果想引用傳值,加個*
即可。
本作品採用《CC 協議》,轉載必須註明作者和本文連結