Hi,大家好,
我是明哥,在自己學習 Golang 的這段時間里,我寫了詳細的學習筆記放在我的個人微信公眾號 《Go編程時光》,對于 Go 語言,我也算是個初學者,因此寫的東西應該會比較適合剛接觸的同學,如果你也是剛學習 Go 語言,不防關注一下,一起學習,一起成長,
我的在線博客:http://golang.iswbm.com
我的 Github:github.com/iswbm/GolangCodingTime
0. 什么是指標
當我們定義一個變數 name
var name string = "Go編程時光"
此時,name 是變數名,它只是編程語言中方便程式員撰寫和理解代碼的一個標簽,
當我們訪問這個標簽時,機算機會回傳給我們它指向的記憶體地址里存盤的值:Go編程時光,
出于某些需要,我們會將這個記憶體地址賦值給另一個變數名,通常叫做 ptr(pointer的簡寫),而這個變數,我們稱之為指標變數,
換句話說,指標變數(一個標簽)的值是指標,也就是記憶體地址,
根據變數指向的值,是否是記憶體地址,我把變數分為兩種:
- 普通變數:存資料值本身
- 指標變數:存值的記憶體地址
1. 指標的創建
指標創建有三種方法
第一種方法
先定義對應的變數,再通過變數取得記憶體地址,創建指標
// 定義普通變數
aint := 1
// 定義指標變數
ptr := &aint
第二種方法
先創建指標,分配好記憶體后,再給指標指向的記憶體地址寫入對應的值,
// 創建指標
astr := new(string)
// 給指標賦值
*astr = "Go編程時光"
第三種方法
先宣告一個指標變數,再從其他變數取得記憶體地址賦值給它
aint := 1
var bint *int // 宣告一個指標
bint = &aint // 初始化
上面的三段代碼中,指標的操作都離不開這兩個符號:
&:從一個普通變數中取得記憶體地址*:當*在賦值操作值的右邊,是從一個指標變數中取得變數值,當*在賦值操作值的左邊,是指該指標指向的變數
通過下面這段代碼,你可以熟悉這兩個符號的用法
package main
import "fmt"
func main() {
aint := 1 // 定義普通變數
ptr := &aint // 定義指標變數
fmt.Println("普通變數存盤的是:", aint)
fmt.Println("普通變數存盤的是:", *ptr)
fmt.Println("指標變數存盤的是:", &aint)
fmt.Println("指標變數存盤的是:", ptr)
}
輸出如下
普通變數存盤的是: 1
普通變數存盤的是: 1
指標變數存盤的是: 0xc0000100a0
指標變數存盤的是: 0xc0000100a0
要想列印指標指向的記憶體地址,方法有兩種
// 第一種
fmt.Printf("%p", ptr)
// 第二種
fmt.Println(ptr)
2. 指標的型別
我們知道字串的型別是 string,整型是int,那么指標如何表示呢?
寫段代碼試驗一下就知道了
package main
import "fmt"
func main() {
astr := "hello"
aint := 1
abool := false
arune := 'a'
afloat := 1.2
fmt.Printf("astr 指標型別是:%T\n", &astr)
fmt.Printf("aint 指標型別是:%T\n", &aint)
fmt.Printf("abool 指標型別是:%T\n", &abool)
fmt.Printf("arune 指標型別是:%T\n", &arune)
fmt.Printf("afloat 指標型別是:%T\n", &afloat)
}
輸出如下,可以發現用 *+所指向變數值的資料型別,就是對應的指標型別,
astr 指標型別是:*string
aint 指標型別是:*int
abool 指標型別是:*bool
arune 指標型別是:*int32
afloat 指標型別是:*float64
所以若我們定義一個只接收指標型別的引數的函式,可以這么寫
func mytest(ptr *int) {
fmt.Println(*ptr)
}
3. 指標的零值
當指標宣告后,沒有進行初始化,其零值是 nil,
func main() {
a := 25
var b *int // 宣告一個指標
if b == nil {
fmt.Println(b)
b = &a // 初始化:將a的記憶體地址給b
fmt.Println(b)
}
}
輸出如下
<nil>
0xc0000100a0
4. 指標與切片
切片與指標一樣,都是參考型別,
如果我們想通過一個函式改變一個陣列的值,有兩種方法
- 將這個陣列的切片做為引數傳給函式
- 將這個陣列的指標做為引數傳給函式
盡管二者都可以實作我們的目的,但是按照 Go 語言的使用習慣,建議使用第一種方法,因為第一種方法,寫出來的代碼會更加簡潔,易讀,具體你可以引數下面兩種方法的代碼實作
使用切片
func modify(sls []int) {
sls[0] = 90
}
func main() {
a := [3]int{89, 90, 91}
modify(a[:])
fmt.Println(a)
}
使用指標
func modify(arr *[3]int) {
(*arr)[0] = 90
}
func main() {
a := [3]int{89, 90, 91}
modify(&a)
fmt.Println(a)
}
系列導讀
01. 開發環境的搭建(Goland & VS Code)
02. 學習五種變數創建的方法
03. 詳解資料型別:****整形與浮點型
04. 詳解資料型別:byte、rune與string
05. 詳解資料型別:陣列與切片
06. 詳解資料型別:字典與布爾型別
07. 詳解資料型別:指標
08. 面向物件編程:結構體與繼承
09. 一篇文章理解 Go 里的函式
10. Go語言流程控制:if-else 條件陳述句
11. Go語言流程控制:switch-case 選擇陳述句
12. Go語言流程控制:for 回圈陳述句
13. Go語言流程控制:goto 無條件跳轉
14. Go語言流程控制:defer 延遲呼叫
15. 面向物件編程:介面與多型
16. 關鍵字:make 和 new 的區別?
17. 一篇文章理解 Go 里的陳述句塊與作用域
18. 學習 Go 協程:goroutine
19. 學習 Go 協程:詳解信道/通道
20. 幾個信道死鎖經典錯誤案例詳解
21. 學習 Go 協程:WaitGroup
22. 學習 Go 協程:互斥鎖和讀寫鎖
23. Go 里的例外處理:panic 和 recover
24. 超詳細解讀 Go Modules 前世今生及入門使用
25. Go 語言中關于包匯入必學的 8 個知識點
26. 如何開源自己寫的模塊給別人用?
27. 說說 Go 語言中的型別斷言?
28. 這五點帶你理解Go語言的select用法

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/17388.html
標籤:Go
上一篇:吾八哥學k8s(四):kubernetes常用基本命令
下一篇:[go]包和工程管理
