一文帶你了解Go語(yǔ)言中的指針和結(jié)構(gòu)體
前言
前面的兩篇文章對(duì) Go 語(yǔ)言的基礎(chǔ)語(yǔ)法和基本數(shù)據(jù)類(lèi)型以及幾個(gè)復(fù)合數(shù)據(jù)類(lèi)型進(jìn)行介紹,本文將對(duì) Go 里面的指針和結(jié)構(gòu)體進(jìn)行介紹,也為后續(xù)文章做鋪墊。
指針
在 Go 語(yǔ)言中,指針可以簡(jiǎn)單理解是一個(gè)地址,指針類(lèi)型是依托于某一個(gè)類(lèi)型而存在的,例如 Go 里面的基本數(shù)據(jù)類(lèi)型 int、float64、string 等,它們所對(duì)應(yīng)的指針類(lèi)型為 *int、*float64、*string等。
指針的定義
語(yǔ)法格式:var 指針變量名 *數(shù)據(jù)類(lèi)型 = &變量。
& 為取地址符號(hào),通過(guò) & 符號(hào)獲取某個(gè)變量的地址,然后賦值給指針變量。
import (
"fmt"
)
func main() {
var num int = 666
var numPtr *int = &num
fmt.Println(numPtr) // num 變量的地址值 0xc00001c098
fmt.Println(&numPtr) // 指針變量本身的地址值 0xc00000a028
}npmPtr 指針變量指向變量 num,0xc00001c098 為 num 變量的地址,0xc00000a028 為指針變量本身的地址值。

使用 new(T) 函數(shù)創(chuàng)建指針變量
import (
"fmt"
)
func main() {
numPtr := new(int)
fmt.Println(numPtr) // 0xc000122058
fmt.Println(*numPtr) // 0
}new(T) 函數(shù)為每個(gè)類(lèi)型分配一片內(nèi)存,內(nèi)存單元保存的是對(duì)應(yīng)類(lèi)型的零值,函數(shù)返回一個(gè)指針類(lèi)型。
錯(cuò)誤的類(lèi)型地址賦值
func main() {
var num float64 = 666
var numPtr *int = &num // cannot use &num (value of type *float64) as type *int in variable declaration
}當(dāng)指針?biāo)劳械念?lèi)型與變量的類(lèi)型不一致時(shí),Go 編譯器會(huì)報(bào)錯(cuò),類(lèi)型不匹配。
獲取和修改指針?biāo)赶蜃兞康闹?/h3>
通過(guò)指針獲取所指向變量的值
func main() {
var num int = 666
var numPtr *int = &num
// 獲取 num 的值
fmt.Println(*numPtr) // 666
}對(duì)指針使用 * 操作符可以獲取所指向變量的值。
通過(guò)指針修改所指向變量的值
import (
"fmt"
)
func main() {
var num int = 666
var numPtr *int = &num
// 修改 num 的值
*numPtr = 555
fmt.Println(num) // 555
}同時(shí)也可以對(duì)指針使用 * 操作符修改所指向變量的值。
結(jié)構(gòu)體
通過(guò)上一篇文章,我們了解了數(shù)組和切片的特點(diǎn),它們可以存儲(chǔ)一組相同類(lèi)型的數(shù)據(jù),而結(jié)構(gòu)體,它可以由 0 個(gè)或多個(gè)字段組成,每個(gè)字段的數(shù)據(jù)類(lèi)型可以一樣,也可以不一樣。結(jié)構(gòu)體可以表示一個(gè)對(duì)象,例如:人,人包含的一些字段有姓名、性別和年齡等。
結(jié)構(gòu)體定義
語(yǔ)法格式:
type XXX struct {
/*
結(jié)構(gòu)體字段定義區(qū)域
*/
}XXX 為結(jié)構(gòu)體的名字,下面以人為對(duì)象,引入結(jié)構(gòu)體
// Person定義一個(gè)人的結(jié)構(gòu)體
type Person struct {
// 姓名
Name string
// 年齡
Age int
// 性別
Sex string
// 身份證號(hào)
idNumber string
}上述代碼定義了人的結(jié)構(gòu)體 Person,包含四個(gè)字段,字段的命名規(guī)則和變量是一樣的,前三個(gè)字段首字母大寫(xiě),可以被包外訪(fǎng)問(wèn),第四個(gè)字段首字母小寫(xiě),表示只能在包內(nèi)訪(fǎng)問(wèn)。 除了上述的定義方式以外,結(jié)構(gòu)體里還可以?xún)?nèi)嵌結(jié)構(gòu)體
// Person 定義一個(gè)人的結(jié)構(gòu)體
type Person struct {
// 姓名
Name string
// 年齡
Age int
// 性別
Sex string
// 身份證號(hào)
idNumber string
}
// Phone 手機(jī)結(jié)構(gòu)體
type Phone struct {
// 品牌
Brand string
// 擁有者
Owner Person
}上述代碼定義了 Person 結(jié)構(gòu)體和 Phone 結(jié)構(gòu)體,Phone 結(jié)構(gòu)體擁有兩個(gè)字段,分別為 Brand 品牌和 Owner 擁有者,Owner 屬性的類(lèi)型,指定為我們所自定義的 Person 結(jié)構(gòu)體。以這種方式定義的結(jié)構(gòu)體字段,我們可以稱(chēng)為嵌入字段(Embedded Field)。也可以將這種字段稱(chēng)為匿名字段。
結(jié)構(gòu)體的創(chuàng)建方式
1、聲明一個(gè)結(jié)構(gòu)體變量
// Person 定義一個(gè)人的結(jié)構(gòu)體
type Person struct {
// 姓名
Name string
// 年齡
Age int
// 性別
Sex string
// 身份證號(hào)
idNumber string
}
func main() {
var person Person
fmt.Println(person.Name) // ""
fmt.Println(person.Age) // 0
fmt.Println(person.Sex) // ""
fmt.Println(person.idNumber) // ""
// 修改結(jié)構(gòu)體字段的值
person.Name = "chenmingyong"
fmt.Println(person.Name) // "chenmingyong"
}
通過(guò)聲明一個(gè)結(jié)構(gòu)體變量,隱式創(chuàng)建一個(gè)結(jié)構(gòu)體變量,這個(gè)結(jié)構(gòu)體變量各個(gè)字段值默認(rèn)為零值,也就是對(duì)應(yīng)類(lèi)型的默認(rèn)值。
結(jié)構(gòu)體屬性的值,可以通過(guò) 變量.字段名 的方式獲取,同時(shí)也可以通過(guò)此方式對(duì)字段值進(jìn)行修改。
2、使用復(fù)合字面值進(jìn)行顯式初始化結(jié)構(gòu)體對(duì)象
import "fmt"
// Person 定義一個(gè)人的結(jié)構(gòu)體
type Person struct {
// 姓名
Name string
// 年齡
Age int
// 性別
Sex string
// 身份證號(hào)
idNumber string
}
func main() {
person := Person{
"chenmingyong",
18,
"男",
"xxxxxxxxx",
}
fmt.Println(person) // {chenmingyong 18 男 xxxxxxxxx}
}上述代碼根據(jù)字段的順序進(jìn)行賦值,實(shí)際上,Go 語(yǔ)言并不推薦我們用這種方式進(jìn)行賦值,因?yàn)榭赡軙?huì)帶來(lái)一些問(wèn)題,例如結(jié)構(gòu)體的某個(gè)中間的字段被刪除或者字段的順序改變了,那么我們需要維護(hù)對(duì)應(yīng)代碼,調(diào)整賦值的順序。
上述創(chuàng)建結(jié)構(gòu)體的方式有弊端,因此我們需要換一種方法,如下第三種方法。
3、 使用 field:value 形式的復(fù)合字面值進(jìn)行顯式初始化結(jié)構(gòu)體對(duì)象
import "fmt"
// Person 定義一個(gè)人的結(jié)構(gòu)體
type Person struct {
// 姓名
Name string
// 年齡
Age int
// 性別
Sex string
// 身份證號(hào)
idNumber string
}
func main() {
person := Person{
Sex: "男",
Age: 18,
Name: "chenmingyong",
idNumber: "xxxxxxxxx",
}
fmt.Println(person) // {chenmingyong 18 男 xxxxxxxxx}
}通過(guò)以上的方式,我們就不被字段的順序所約束了。
4、通過(guò) new(T) 函數(shù)創(chuàng)建結(jié)構(gòu)體指針
// Person 定義一個(gè)人的結(jié)構(gòu)體
type Person struct {
// 姓名
Name string
// 年齡
Age int
// 性別
Sex string
// 身份證號(hào)
idNumber string
}
func main() {
person := new(Person)
(*person).Name = "chenmignyong"
fmt.Println((*person).Name) // chenmignyong
// 簡(jiǎn)化賦值,底層自動(dòng)轉(zhuǎn)換成 (*person).Age = 18
person.Age = 18
fmt.Println(person.Age) // 18
}前面提到過(guò),訪(fǎng)問(wèn)指針?biāo)赶蜃兞康闹?,需要使?* 操作符,但在結(jié)構(gòu)體這里有點(diǎn)特殊,如果不加 * 的話(huà),底層會(huì)將 person.Age = 18 轉(zhuǎn)成 (*person).Age = 18。
小結(jié)
本文對(duì)指針和結(jié)構(gòu)體進(jìn)行了介紹,也指出使用指針和結(jié)構(gòu)體時(shí)需要注意的一些地方。因?yàn)楸疚氖腔诹私獾膶用嫒?xiě)的文章,一些深入的知識(shí)并沒(méi)有提到,然后也沒(méi)有提到結(jié)構(gòu)體的方法,是因?yàn)榇蛩懔舻胶竺婧秃瘮?shù)一起去介紹。
到此這篇關(guān)于一文帶你了解Go語(yǔ)言中的指針和結(jié)構(gòu)體的文章就介紹到這了,更多相關(guān)Go語(yǔ)言指針 結(jié)構(gòu)體內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang如何使用gos7讀取S7200Smart數(shù)據(jù)
文章介紹了如何使用Golang語(yǔ)言的Gos7工具庫(kù)讀取西門(mén)子S7200Smart系列PLC的數(shù)據(jù),通過(guò)指定數(shù)據(jù)塊號(hào)、起始字節(jié)偏移量和數(shù)據(jù)長(zhǎng)度,可以精確讀取所需的數(shù)據(jù),感興趣的朋友跟隨小編一起看看吧2024-12-12
go?time.After優(yōu)化后性能提升34%內(nèi)存減少67%
這篇文章主要介紹了go語(yǔ)言time.After優(yōu)化后性能提升34%內(nèi)存減少67%實(shí)例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
基于Go編寫(xiě)一個(gè)可視化Navicat本地密碼解析器
這篇文章主要給大家介紹了基于Go編寫(xiě)一個(gè)可視化Navicat本地密碼解析器的方法,文中有詳細(xì)的代碼示例和圖文介紹,有需要的朋友可以參考閱讀本文2023-08-08
使用Golang開(kāi)發(fā)一個(gè)簡(jiǎn)易版shell
這篇文章主要為大家詳細(xì)介紹了如何使用Golang開(kāi)發(fā)一個(gè)簡(jiǎn)易版shell,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02

