在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ GO/ 4.9 指針
4.7 strings 和 strconv 包
13.6 啟動(dòng)外部命令和程序
?# 11.4 類型判斷:type-switch
12.1 讀取用戶的輸入
10.6 方法
12.2 文件讀寫
13 錯(cuò)誤處理與測(cè)試
9.3 鎖和 sync 包
12.3 文件拷貝
?# 11.7 第一個(gè)例子:使用 Sorter 接口排序
?# 11.5 測(cè)試一個(gè)值是否實(shí)現(xiàn)了某個(gè)接口
6.4 defer 和追蹤
12.10 XML 數(shù)據(jù)格式
13.10 性能調(diào)試:分析并優(yōu)化 Go 程序
?# 11.1 接口是什么
2.2 Go 環(huán)境變量
2.6 安裝目錄清單
2.5 在 Windows 上安裝 Go
11.11 Printf 和反射
1.2 語言的主要特性與發(fā)展的環(huán)境和影響因素
9.0 包(package)
7.4 切片重組(reslice)
13.2 運(yùn)行時(shí)異常和 panic
10.2 使用工廠方法創(chuàng)建結(jié)構(gòu)體實(shí)例
12.8 使用接口的實(shí)際例子:fmt.Fprintf
2.4 在 Mac OS X 上安裝 Go
3.8 Go 性能說明
7.2 切片
8.0 Map
3.1 Go 開發(fā)環(huán)境的基本要求
5.6 標(biāo)簽與 goto
6.10 使用閉包調(diào)試
9.5 自定義包和可見性
4.3 常量
?# 11.2 接口嵌套接口
6.5 內(nèi)置函數(shù)
前言
10.8 垃圾回收和 SetFinalizer
2.8 Go 解釋器
13.7 Go 中的單元測(cè)試和基準(zhǔn)測(cè)試
6.8 閉包
4.9 指針
13.1 錯(cuò)誤處理
10.1 結(jié)構(gòu)體定義
5.1 if-else 結(jié)構(gòu)
6.6 遞歸函數(shù)
9.9 通過 Git 打包和安裝
2.7 Go 運(yùn)行時(shí)(runtime)
10.7 類型的 String() 方法和格式化描述符
3.7 其它工具
9.6 為自定義包使用 godoc
11.12 接口與動(dòng)態(tài)類型
13.3 從 panic 中恢復(fù)(Recover)
10.3 使用自定義包中的結(jié)構(gòu)體
11.14 結(jié)構(gòu)體、集合和高階函數(shù)
3.6 生成代碼文檔
9.2 regexp 包
4.1 文件名、關(guān)鍵字與標(biāo)識(shí)符
?# 11.6 使用方法集與接口
7.0 數(shù)組與切片
7.1 聲明和初始化
12.11 用 Gob 傳輸數(shù)據(jù)
5.5 Break 與 continue
1.1 起源與發(fā)展
?# 11 接口(Interfaces)與反射(reflection)
6.9 應(yīng)用閉包:將函數(shù)作為返回值
4.2 Go 程序的基本結(jié)構(gòu)和要素
8.6 將 map 的鍵值對(duì)調(diào)
6.11 計(jì)算函數(shù)執(zhí)行時(shí)間
5.0 控制結(jié)構(gòu)
10.5 匿名字段和內(nèi)嵌結(jié)構(gòu)體
4.6 字符串
3.0 編輯器、集成開發(fā)環(huán)境與其它工具
13.8 測(cè)試的具體例子
7.6 字符串、數(shù)組和切片的應(yīng)用
8.4 map 類型的切片
3.9 與其它語言進(jìn)行交互
7.3 For-range 結(jié)構(gòu)
9.7 使用 go install 安裝自定義包
6.0 函數(shù)
9.8 自定義包的目錄結(jié)構(gòu)、go install 和 go test
6.3 傳遞變長(zhǎng)參數(shù)
13.9 用(測(cè)試數(shù)據(jù))表驅(qū)動(dòng)測(cè)試
11.9 空接口
8.1 聲明、初始化和 make
6.2 函數(shù)參數(shù)與返回值
9.11 在 Go 程序中使用外部庫
3.3 調(diào)試器
4.5 基本類型和運(yùn)算符
?# 11.8 第二個(gè)例子:讀和寫
12.5 用 buffer 讀取文件
總結(jié):Go 中的面向?qū)ο?/span>
11.10 反射包
12.7 用 defer 關(guān)閉文件
9.4 精密計(jì)算和 big 包
4.4 變量
6.1 介紹
13.4 自定義包中的錯(cuò)誤處理和 panicking
12.4 從命令行讀取參數(shù)
9.10 Go 的外部包和項(xiàng)目
8.3 for-range 的配套用法
3.5 格式化代碼
10.4 帶標(biāo)簽的結(jié)構(gòu)體
7.5 切片的復(fù)制與追加
?# 11.3 類型斷言:如何檢測(cè)和轉(zhuǎn)換接口變量的類型
5.4 for 結(jié)構(gòu)
4.8 時(shí)間和日期
2.3 在 Linux 上安裝 Go
12 讀寫數(shù)據(jù)
6.12 通過內(nèi)存緩存來提升性能
9.1 標(biāo)準(zhǔn)庫概述
12.6 用切片讀寫文件
10 結(jié)構(gòu)(struct)與方法(method)
8.5 map 的排序
12.9 JSON 數(shù)據(jù)格式
13.5 一種用閉包處理錯(cuò)誤的模式
3.2 編輯器和集成開發(fā)環(huán)境
12.12 Go 中的密碼學(xué)
5.2 測(cè)試多返回值函數(shù)的錯(cuò)誤
6.7 將函數(shù)作為參數(shù)
8.2 測(cè)試鍵值對(duì)是否存在及刪除元素
3.4 構(gòu)建并運(yùn)行 Go 程序
2.1 平臺(tái)與架構(gòu)
5.3 switch 結(jié)構(gòu)

4.9 指針

不像 Java 和 .NET,Go 語言為程序員提供了控制數(shù)據(jù)結(jié)構(gòu)的指針的能力;但是,你不能進(jìn)行指針運(yùn)算。通過給予程序員基本內(nèi)存布局,Go 語言允許你控制特定集合的數(shù)據(jù)結(jié)構(gòu)、分配的數(shù)量以及內(nèi)存訪問模式,這些對(duì)構(gòu)建運(yùn)行良好的系統(tǒng)是非常重要的:指針對(duì)于性能的影響是不言而喻的,而如果你想要做的是系統(tǒng)編程、操作系統(tǒng)或者網(wǎng)絡(luò)應(yīng)用,指針更是不可或缺的一部分。

由于各種原因,指針對(duì)于使用面向?qū)ο缶幊痰默F(xiàn)代程序員來說可能顯得有些陌生,不過我們將會(huì)在這一小節(jié)對(duì)此進(jìn)行解釋,并在未來的章節(jié)中展開深入討論。

程序在內(nèi)存中存儲(chǔ)它的值,每個(gè)內(nèi)存塊(或字)有一個(gè)地址,通常用十六進(jìn)制數(shù)表示,如:0x6b08200xf84001d7f0。

Go 語言的取地址符是 &,放到一個(gè)變量前使用就會(huì)返回相應(yīng)變量的內(nèi)存地址。

下面的代碼片段(示例 4.9 pointer.go)可能輸出 An integer: 5, its location in memory: 0x6b0820(這個(gè)值隨著你每次運(yùn)行程序而變化)。

var i1 = 5
fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1)

這個(gè)地址可以存儲(chǔ)在一個(gè)叫做指針的特殊數(shù)據(jù)類型中,在本例中這是一個(gè)指向 int 的指針,即 i1:此處使用 *int 表示。如果我們想調(diào)用指針 intP,我們可以這樣聲明它:

var intP *int

然后使用 intP = &i1 是合法的,此時(shí) intP 指向 i1。

(指針的格式化標(biāo)識(shí)符為 %p

intP 存儲(chǔ)了 i1 的內(nèi)存地址;它指向了 i1 的位置,它引用了變量 i1。

一個(gè)指針變量可以指向任何一個(gè)值的內(nèi)存地址 它指向那個(gè)值的內(nèi)存地址,在 32 位機(jī)器上占用 4 個(gè)字節(jié),在 64 位機(jī)器上占用 8 個(gè)字節(jié),并且與它所指向的值的大小無關(guān)。當(dāng)然,可以聲明指針指向任何類型的值來表明它的原始性或結(jié)構(gòu)性;你可以在指針類型前面加上 號(hào)(前綴)來獲取指針?biāo)赶虻膬?nèi)容,這里的 號(hào)是一個(gè)類型更改器。使用一個(gè)指針引用一個(gè)值被稱為間接引用。

當(dāng)一個(gè)指針被定義后沒有分配到任何變量時(shí),它的值為 nil。

一個(gè)指針變量通常縮寫為 ptr。

注意事項(xiàng)

在書寫表達(dá)式類似 var p *type 時(shí),切記在 號(hào)和指針名稱間留有一個(gè)空格,因?yàn)?`- var ptype` 是語法正確的,但是在更復(fù)雜的表達(dá)式中,它容易被誤認(rèn)為是一個(gè)乘法表達(dá)式!

符號(hào) 可以放在一個(gè)指針前,如 `intP`,那么它將得到這個(gè)指針指向地址上所存儲(chǔ)的值;這被稱為反引用(或者內(nèi)容或者間接引用)操作符;另一種說法是指針轉(zhuǎn)移。

對(duì)于任何一個(gè)變量 var, 如下表達(dá)式都是正確的:var == *(&var)。

現(xiàn)在,我們應(yīng)當(dāng)能理解 pointer.go 的全部?jī)?nèi)容及其輸出:

示例 4.21 pointer.go:

package main
import "fmt"
func main() {
    var i1 = 5
    fmt.Printf("An integer: %d, its location in memory: %p\n", i1, &i1)
    var intP *int
    intP = &i1
    fmt.Printf("The value at memory location %p is %d\n", intP, *intP)
}

輸出:

An integer: 5, its location in memory: 0x24f0820
The value at memory location 0x24f0820 is 5

我們可以用下圖來表示內(nèi)存使用的情況:

http://wiki.jikexueyuan.com/project/the-way-to-go/images/4.4.9_fig4.4.png?raw=true" alt="" />

程序 string_pointer.go 為我們展示了指針對(duì)string的例子。

它展示了分配一個(gè)新的值給 *p 并且更改這個(gè)變量自己的值(這里是一個(gè)字符串)。

示例 4.22 string_pointer.go

package main
import "fmt"
func main() {
    s := "good bye"
    var p *string = &s
    *p = "ciao"
    fmt.Printf("Here is the pointer p: %p\n", p) // prints address
    fmt.Printf("Here is the string *p: %s\n", *p) // prints string
    fmt.Printf("Here is the string s: %s\n", s) // prints same string
}

輸出:

Here is the pointer p: 0x2540820
Here is the string *p: ciao
Here is the string s: ciao

通過對(duì) *p 賦另一個(gè)值來更改“對(duì)象”,這樣 s 也會(huì)隨之更改。

內(nèi)存示意圖如下:

http://wiki.jikexueyuan.com/project/the-way-to-go/images/4.4.9_fig4.5.png?raw=true" alt="" />

注意事項(xiàng)

你不能得到一個(gè)文字或常量的地址,例如:

const i = 5
ptr := &i //error: cannot take the address of i
ptr2 := &10 //error: cannot take the address of 10

所以說,Go 語言和 C、C++ 以及 D 語言這些低級(jí)(系統(tǒng))語言一樣,都有指針的概念。但是對(duì)于經(jīng)常導(dǎo)致 C 語言內(nèi)存泄漏繼而程序崩潰的指針運(yùn)算(所謂的指針?biāo)惴?,如?code>pointer+2,移動(dòng)指針指向字符串的字節(jié)數(shù)或數(shù)組的某個(gè)位置)是不被允許的。Go 語言中的指針保證了內(nèi)存安全,更像是 Java、C# 和 VB.NET 中的引用。

因此 c = *p++ 在 Go 語言的代碼中是不合法的。

指針的一個(gè)高級(jí)應(yīng)用是你可以傳遞一個(gè)變量的引用(如函數(shù)的參數(shù)),這樣不會(huì)傳遞變量的拷貝。指針傳遞是很廉價(jià)的,只占用 4 個(gè)或 8 個(gè)字節(jié)。當(dāng)程序在工作中需要占用大量的內(nèi)存,或很多變量,或者兩者都有,使用指針會(huì)減少內(nèi)存占用和提高效率。被指向的變量也保存在內(nèi)存中,直到?jīng)]有任何指針指向它們,所以從它們被創(chuàng)建開始就具有相互獨(dú)立的生命周期。

另一方面(雖然不太可能),由于一個(gè)指針導(dǎo)致的間接引用(一個(gè)進(jìn)程執(zhí)行了另一個(gè)地址),指針的過度頻繁使用也會(huì)導(dǎo)致性能下降。

指針也可以指向另一個(gè)指針,并且可以進(jìn)行任意深度的嵌套,導(dǎo)致你可以有多級(jí)的間接引用,但在大多數(shù)情況這會(huì)使你的代碼結(jié)構(gòu)不清晰。

如我們所見,在大多數(shù)情況下 Go 語言可以使程序員輕松創(chuàng)建指針,并且隱藏間接引用,如:自動(dòng)反向引用。

對(duì)一個(gè)空指針的反向引用是不合法的,并且會(huì)使程序崩潰:

示例 4.23 testcrash.go:

package main
func main() {
    var p *int = nil
    *p = 0
}
// in Windows: stops only with: <exit code="-1073741819" msg="process crashed"/>
// runtime error: invalid memory address or nil pointer dereference

問題 4.2 列舉 Go 語言中 * 號(hào)的所有用法。

鏈接