<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                不像 Java 和 .NET,Go 語言為程序員提供了控制數據結構的指針的能力;但是,你不能進行指針運算。通過給予程序員基本內存布局,Go 語言允許你控制特定集合的數據結構、分配的數量以及內存訪問模式,這些對構建運行良好的系統是非常重要的:指針對于性能的影響是不言而喻的,而如果你想要做的是系統編程、操作系統或者網絡應用,指針更是不可或缺的一部分。 由于各種原因,指針對于使用面向對象編程的現代程序員來說可能顯得有些陌生,不過我們將會在這一小節對此進行解釋,并在未來的章節中展開深入討論。 程序在內存中存儲它的值,每個內存塊(或字)有一個地址,通常用十六進制數表示,如:`0x6b0820`?或`0xf84001d7f0`。 Go 語言的取地址符是?`&`,放到一個變量前使用就會返回相應變量的內存地址。 下面的代碼片段(示例 4.9?[pointer.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_4/pointer.go))可能輸出?`An integer: 5, its location in memory: 0x6b0820`(這個值隨著你每次運行程序而變化)。 ~~~ var i1 = 5 fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1) ~~~ 這個地址可以存儲在一個叫做指針的特殊數據類型中,在本例中這是一個指向 int 的指針,即?`i1`:此處使用 *int 表示。如果我們想調用指針 intP,我們可以這樣聲明它: ~~~ var intP *int ~~~ 然后使用?`intP = &i1`?是合法的,此時 intP 指向 i1。 (指針的格式化標識符為?`%p`) intP 存儲了 i1 的內存地址;它指向了 i1 的位置,它引用了變量 i1。 **一個指針變量可以指向任何一個值的內存地址**?它指向那個值的內存地址,在 32 位機器上占用 4 個字節,在 64 位機器上占用 8 個字節,并且與它所指向的值的大小無關。當然,可以聲明指針指向任何類型的值來表明它的原始性或結構性;你可以在指針類型前面加上 * 號(前綴)來獲取指針所指向的內容,這里的 * 號是一個類型更改器。使用一個指針引用一個值被稱為間接引用。 當一個指針被定義后沒有分配到任何變量時,它的值為?`nil`。 一個指針變量通常縮寫為?`ptr`。 > **注意事項** > 在書寫表達式類似?`var p *type`?時,切記在 * 號和指針名稱間留有一個空格,因為?`- var p*type`?是語法正確的,但是在更復雜的表達式中,它容易被誤認為是一個乘法表達式! 符號 * 可以放在一個指針前,如?`*intP`,那么它將得到這個指針指向地址上所存儲的值;這被稱為反引用(或者內容或者間接引用)操作符;另一種說法是指針轉移。 對于任何一個變量 var, 如下表達式都是正確的:`var == *(&var)`。 現在,我們應當能理解 pointer.go 中的整個程序和他的輸出: 示例 4.21?[pointer.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_4/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 ~~~ 我們可以用下圖來表示內存使用的情況: [![](https://github.com/Unknwon/the-way-to-go_ZH_CN/raw/master/images/4.4.9_fig4.4.png?raw=true)](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/images/4.4.9_fig4.4.png?raw=true) 程序 string_pointer.go 為我們展示了指針對string的例子。 它展示了分配一個新的值給 *p 并且更改這個變量自己的值(這里是一個字符串)。 示例 4.22?[string_pointer.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_4/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 ~~~ 通過對 *p 賦另一個值來更改“對象”,這樣 s 也會隨之更改。 內存示意圖如下: [![](https://github.com/Unknwon/the-way-to-go_ZH_CN/raw/master/images/4.4.9_fig4.5.png?raw=true)](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/images/4.4.9_fig4.5.png?raw=true) **注意事項** 你不能得到一個文字或常量的地址,例如: ~~~ 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 語言這些低級(系統)語言一樣,都有指針的概念。但是對于經常導致 C 語言內存泄漏繼而程序崩潰的指針運算(所謂的指針算法,如:`pointer+2`,移動指針指向字符串的字節數或數組的某個位置)是不被允許的。Go 語言中的指針保證了內存安全,更像是 Java、C# 和 VB.NET 中的引用。 因此?`c = *p++`?在 Go 語言的代碼中是不合法的。 指針的一個高級應用是你可以傳遞一個變量的引用(如函數的參數),這樣不會傳遞變量的拷貝。指針傳遞是很廉價的,只占用 4 個或 8 個字節。當程序在工作中需要占用大量的內存,或很多變量,或者兩者都有,使用指針會減少內存占用和提高效率。被指向的變量也保存在內存中,直到沒有任何指針指向它們,所以從它們被創建開始就具有相互獨立的生命周期。 另一方面(雖然不太可能),由于一個指針導致的間接引用(一個進程執行了另一個地址),指針的過度頻繁使用也會導致性能下降。 指針也可以指向另一個指針,并且可以進行任意深度的嵌套,導致你可以有多級的間接引用,但在大多數情況這會使你的代碼結構不清晰。 如我們所見,在大多數情況下 Go 語言可以使程序員輕松創建指針,并且隱藏間接引用,如:自動反向引用。 對一個空指針的反向引用是不合法的,并且會使程序崩潰: 示例 4.23?[testcrash.go](https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/examples/chapter_4/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 語言中 * 號的所有用法。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看