[TOC]
# 指針
3個概念:指針地址、指針類型和指針取值
2個符號:`&`(取地址)和`*`(根據地址取值)。
## 指針地址和指針類型
`&`字符放在變量前面對變量進行“取地址”操作
Go語言中的值類型(int、float、bool、string、array、struct)都有對應的指針類型,如:`*int`、`*int64`、`*string`等。
~~~go
ptr := &v // v的類型為T
~~~
* v:代表被取地址的變量,類型為`T`
* ptr:用于接收地址的變量,ptr的類型就為`*T`,稱做T的指針類型。\*代表指針。
eg:
~~~go
func main() {
a := 10
b := &a
fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
fmt.Println(&b) // 0xc00000e018
}
~~~
`b := &a`

## 指針取值
在對普通變量使用&操作符取地址后會獲得這個變量的指針,然后可以對指針使用`*`操作,也就是指針取值
~~~go
func main() {
//指針取值
a := 10
b := &a // 取變量a的地址,將指針保存到b中
fmt.Printf("type of b:%T\n", b)
c := *b // 指針取值(根據指針去內存取值)
fmt.Printf("type of c:%T\n", c)
fmt.Printf("value of c:%v\n", c)
}
~~~
output:
~~~go
type of b:*int
type of c:int
value of c:10
~~~
取地址操作符`&`和取值操作符`*`是一對互補操作符,`&`取出地址,`*`根據地址取出地址指向的值。
變量、指針地址、指針變量、取地址、取值的相互關系和特性如下:
* 對變量進行取地址(&)操作,可以獲得這個變量的指針變量。
* 指針變量的值是指針地址。
* 對指針變量進行取值(*)操作,可以獲得指針變量指向的原變量的值。
**指針傳值示例:**
~~~go
func modify1(x int) {
x = 100
}
func modify2(x *int) {
*x = 100
}
func main() {
a := 10
modify1(a)
fmt.Println(a) // 10
modify2(&a)
fmt.Println(a) // 100
}
~~~
## new和make
### new
new是一個內置的函數:
~~~go
func new(Type) *Type
~~~
* Type表示類型,new函數只接受一個參數,這個參數是一個類型
* \*Type表示類型指針,new函數返回一個指向該類型內存地址的指針。
new函數得到的是一個類型的指針,并且該指針對應的值為該類型的零值
~~~go
func main() {
a := new(int)
b := new(bool)
fmt.Printf("%T\n", a) // *int
fmt.Printf("%T\n", b) // *bool
fmt.Println(*a) // 0
fmt.Println(*b) // false
}
~~~
`var a *int`只是聲明了一個指針變量a但是沒有初始化,指針作為引用類型需要初始化后才會擁有內存空間,才可以給它賦值。應該按照如下方式使用內置的new函數對a進行初始化之后就可以正常對其賦值了:
~~~go
func main() {
var a *int
a = new(int)
*a = 10
fmt.Println(*a)
}
~~~
### make
make也是用于內存分配的,只用于`slice、map、chan`的內存創建。
且它返回的類型就是這三個類型本身,而不是他們的指針類型,因為這三種類型就是引用類型,所以就沒有必要返回他們的指針了
~~~go
func make(t Type, size ...IntegerType) Type
~~~
make函數是無可替代的,我們在使用slice、map以及channel的時候,都需要使用make進行初始化,然后才可以對它們進行操作。
`var b map[string]int`只是聲明變量b是一個map類型的變量,需要像下面的示例代碼一樣使用make函數進行初始化操作之后,才能對其進行鍵值對賦值:
~~~go
func main() {
var b map[string]int
b = make(map[string]int, 10)
b["老叮當"] = 18
fmt.Println(b)
}
~~~
### new與make的區別
1. 二者都是用來做內存分配的。
2. make只用于slice、map以及channel的初始化,返回的還是這三個引用類型本身;
3. 而new用于類型的內存分配,并且內存對應的值為類型零值,返回的是指向類型的指針。
- Go準備工作
- 依賴管理
- Go基礎
- 1、變量和常量
- 2、基本數據類型
- 3、運算符
- 4、流程控制
- 5、數組
- 數組聲明和初始化
- 遍歷
- 數組是值類型
- 6、切片
- 定義
- slice其他內容
- 7、map
- 8、函數
- 函數基礎
- 函數進階
- 9、指針
- 10、結構體
- 類型別名和自定義類型
- 結構體
- 11、接口
- 12、反射
- 13、并發
- 14、網絡編程
- 15、單元測試
- Go常用庫/包
- Context
- time
- strings/strconv
- file
- http
- Go常用第三方包
- Go優化
- Go問題排查
- Go框架
- 基礎知識點的思考
- 面試題
- 八股文
- 操作系統
- 整理一份資料
- interface
- array
- slice
- map
- MUTEX
- RWMUTEX
- Channel
- waitGroup
- context
- reflect
- gc
- GMP和CSP
- Select
- Docker
- 基本命令
- dockerfile
- docker-compose
- rpc和grpc
- consul和etcd
- ETCD
- consul
- gin
- 一些小點
- 樹
- K8s
- ES
- pprof
- mycat
- nginx
- 整理后的面試題
- 基礎
- Map
- Chan
- GC
- GMP
- 并發
- 內存
- 算法
- docker