網站首頁 編程語言 正文
前言
前面的兩篇文章對 Go 語言的基礎語法和基本數據類型以及幾個復合數據類型進行介紹,本文將對 Go 里面的指針和結構體進行介紹,也為后續文章做鋪墊。
指針
在 Go
語言中,指針可以簡單理解是一個地址,指針類型是依托于某一個類型而存在的,例如 Go
里面的基本數據類型 int
、float64
、string
等,它們所對應的指針類型為 *int
、*float64
、*string
等。
指針的定義
語法格式:var 指針變量名 *數據類型 = &變量
。
&
為取地址符號,通過 &
符號獲取某個變量的地址,然后賦值給指針變量。
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)
函數創建指針變量
import ( "fmt" ) func main() { numPtr := new(int) fmt.Println(numPtr) // 0xc000122058 fmt.Println(*numPtr) // 0 }
new(T)
函數為每個類型分配一片內存,內存單元保存的是對應類型的零值,函數返回一個指針類型。
錯誤的類型地址賦值
func main() { var num float64 = 666 var numPtr *int = &num // cannot use &num (value of type *float64) as type *int in variable declaration }
當指針所依托的類型與變量的類型不一致時,Go 編譯器會報錯,類型不匹配。
獲取和修改指針所指向變量的值
通過指針獲取所指向變量的值
func main() { var num int = 666 var numPtr *int = &num // 獲取 num 的值 fmt.Println(*numPtr) // 666 }
對指針使用 *
操作符可以獲取所指向變量的值。
通過指針修改所指向變量的值
import ( "fmt" ) func main() { var num int = 666 var numPtr *int = &num // 修改 num 的值 *numPtr = 555 fmt.Println(num) // 555 }
同時也可以對指針使用 *
操作符修改所指向變量的值。
結構體
通過上一篇文章,我們了解了數組和切片的特點,它們可以存儲一組相同類型的數據,而結構體,它可以由 0 個或多個字段組成,每個字段的數據類型可以一樣,也可以不一樣。結構體可以表示一個對象,例如:人,人包含的一些字段有姓名、性別和年齡等。
結構體定義
語法格式:
type XXX struct { /* 結構體字段定義區域 */ }
XXX
為結構體的名字,下面以人為對象,引入結構體
// Person定義一個人的結構體 type Person struct { // 姓名 Name string // 年齡 Age int // 性別 Sex string // 身份證號 idNumber string }
上述代碼定義了人的結構體 Person
,包含四個字段,字段的命名規則和變量是一樣的,前三個字段首字母大寫,可以被包外訪問,第四個字段首字母小寫,表示只能在包內訪問。 除了上述的定義方式以外,結構體里還可以內嵌結構體
// Person 定義一個人的結構體 type Person struct { // 姓名 Name string // 年齡 Age int // 性別 Sex string // 身份證號 idNumber string } // Phone 手機結構體 type Phone struct { // 品牌 Brand string // 擁有者 Owner Person }
上述代碼定義了 Person
結構體和 Phone
結構體,Phone
結構體擁有兩個字段,分別為 Brand
品牌和 Owner
擁有者,Owner
屬性的類型,指定為我們所自定義的 Person
結構體。以這種方式定義的結構體字段,我們可以稱為嵌入字段(Embedded Field)。也可以將這種字段稱為匿名字段。
結構體的創建方式
1、聲明一個結構體變量
// Person 定義一個人的結構體 type Person struct { // 姓名 Name string // 年齡 Age int // 性別 Sex string // 身份證號 idNumber string } func main() { var person Person fmt.Println(person.Name) // "" fmt.Println(person.Age) // 0 fmt.Println(person.Sex) // "" fmt.Println(person.idNumber) // "" // 修改結構體字段的值 person.Name = "chenmingyong" fmt.Println(person.Name) // "chenmingyong" }
通過聲明一個結構體變量,隱式創建一個結構體變量,這個結構體變量各個字段值默認為零值,也就是對應類型的默認值。
結構體屬性的值,可以通過 變量.字段名
的方式獲取,同時也可以通過此方式對字段值進行修改。
2、使用復合字面值進行顯式初始化結構體對象
import "fmt" // Person 定義一個人的結構體 type Person struct { // 姓名 Name string // 年齡 Age int // 性別 Sex string // 身份證號 idNumber string } func main() { person := Person{ "chenmingyong", 18, "男", "xxxxxxxxx", } fmt.Println(person) // {chenmingyong 18 男 xxxxxxxxx} }
上述代碼根據字段的順序進行賦值,實際上,Go 語言并不推薦我們用這種方式進行賦值,因為可能會帶來一些問題,例如結構體的某個中間的字段被刪除或者字段的順序改變了,那么我們需要維護對應代碼,調整賦值的順序。
上述創建結構體的方式有弊端,因此我們需要換一種方法,如下第三種方法。
3、 使用 field:value
形式的復合字面值進行顯式初始化結構體對象
import "fmt" // Person 定義一個人的結構體 type Person struct { // 姓名 Name string // 年齡 Age int // 性別 Sex string // 身份證號 idNumber string } func main() { person := Person{ Sex: "男", Age: 18, Name: "chenmingyong", idNumber: "xxxxxxxxx", } fmt.Println(person) // {chenmingyong 18 男 xxxxxxxxx} }
通過以上的方式,我們就不被字段的順序所約束了。
4、通過 new(T)
函數創建結構體指針
// Person 定義一個人的結構體 type Person struct { // 姓名 Name string // 年齡 Age int // 性別 Sex string // 身份證號 idNumber string } func main() { person := new(Person) (*person).Name = "chenmignyong" fmt.Println((*person).Name) // chenmignyong // 簡化賦值,底層自動轉換成 (*person).Age = 18 person.Age = 18 fmt.Println(person.Age) // 18 }
前面提到過,訪問指針所指向變量的值,需要使用 *
操作符,但在結構體這里有點特殊,如果不加 *
的話,底層會將 person.Age = 18
轉成 (*person).Age = 18
。
小結
本文對指針和結構體進行了介紹,也指出使用指針和結構體時需要注意的一些地方。因為本文是基于了解的層面去寫的文章,一些深入的知識并沒有提到,然后也沒有提到結構體的方法,是因為打算留到后面和函數一起去介紹。
原文鏈接:https://juejin.cn/post/7169961029328175112
相關推薦
- 2022-11-17 Android四種常見布局方式示例教程_Android
- 2022-09-29 Python模塊域名dnspython解析_python
- 2022-07-09 常見的dos命令
- 2022-07-03 axios項目封裝及使用
- 2022-01-17 如何實現 input 和 textarea 自動聚焦
- 2022-12-21 C語言中continue的用法詳解_C 語言
- 2023-01-09 React應用框架Dva數據流向原理總結分析_React
- 2022-02-25 C++的靜態成員變量和靜態成員函數詳解_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支