日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Go語言基礎學習之指針詳解_Golang

作者:程序員祝融 ? 更新時間: 2023-02-06 編程語言

今天來說說 Go 語言基礎中的指針。

Go 語言中指針是很容易學習的,Go 語言中使用指針可以更簡單的執行一些任務。

1. 什么是指針

Go 語言中,一個指針變量指向了一個值的內存地址。和 C、C++ 中的指針不同,Go 語言中的指針不能進行計算和偏移操作。

Go 語言中的函數傳參都是值拷貝,當我們想要修改某個變量的時候,我們可以創建一個指向該變量地址的指針變量。傳遞數據使用指針,而無須拷貝數據。

Go 語言中的指針操作非常簡單,只有記住兩個符號就可以了。

  • &(取地址)
  • *(根據地址取值)
var ip *int /* 指向整型*/

畫個重點,我們想徹底搞明白指針,必須要掌握 3 個概念:

  • 指針地址
  • 指針類型
  • 指針取值

接下來我們從這 3 點大家闡述 Go 語言指針,方便大家掌握。

2. 指針地址 & 指針類型

Go 語言變量在運行時都會被指定一個內存地址,即變量在內存中的位置。Go 語言通常在使用時會在變量前放一個?&?代表對變量進行 “ 取地址 ” 操作。Go 語言常用的值類型 (string、int、array、struct、float、bool )都會有對應的指針類型。如:string、?int、*int64 等。

每個變量在運行時都擁有一個地址,這個地址代表變量在內存中的位置。Go語言中使用&字符放在變量前面對變量進行“取地址”操作。 Go語言中的值類型(int、float、bool、string、array、struct)都有對應的指針類型,如:int、int64、*string等。

取變量指針的語法如下:

package main

import "fmt"

func main(){
        
    a := 10   /* 聲明實際變量 */
    ip := &a  /* 指針變量的存儲地址 */
    
    
    fmt.Printf("a 變量的地址是: %x\n", &a  )
    
    /* 指針變量的存儲地址 */
    fmt.Printf("ip 變量儲存的指針地址: %x\n", ip )
    
    /* 使用指針訪問值 */
    fmt.Printf("*ip 變量的值: %d\n", *ip )
}

運行結果:

a 變量的地址是: 0xc000010200

ip 變量儲存的指針地址: 0xc000010200

*ip 變量的值: 10

其中:

  • a: 代表被取地址的變量,類型為 int
  • ip: 用于接收地址的變量,ip?的類型就為 *int,稱做?int?的指針類型。*代表指針。

用圖來表示一下?ip := &a:

以上就是指針地址和指針類型。

3. 指針取值

對變量使用?&會獲取該變量的指針,對指針使用?*?會獲取到值,也就是 “指正取值”。舉個例子更好的理解一下:

package main

import "fmt"

func main() {
    
    a := 20   /* 聲明實際變量 */
    b := &a  /* 指針變量的存儲地址 */
    fmt.Printf("type of b:%T\n", &a  )
    
    c := *b // 指針取值(根據指針去內存取值)
    fmt.Printf("type of c:%T\n", c)
    fmt.Printf("value of c:%v\n", c)
}

控制臺輸出結果:

type of b:*int
type of c:int
value of c:10

小結一下:

  • 指針變量的值是指針地址 (可以結合上圖更好的理解)
  • 對變量進行取地址?&操作,可以獲得這個變量的指針變量
  • 對指針變量進行取值?*操作,可以獲得指針變量指向的原變量的值

函數傳值:

package main

import "fmt"

func main() {
    
    x := 2
    mod1(x)
    fmt.Println(x) // 2
    
    mod2(&x)
    fmt.Println(x) // 1024
}

func mod1(x int) {
    x = 1024
}

func mod2(x *int) {
    *x = 1024
}

4. 空指針

當一個指針被定義后沒有分配到任何變量時,它的值為?nil

nil?指針也稱為空指針。

nil在概念上和其它語言的?null、None、nil、NULL一樣,都指代零值或空值。

一個指針變量通常縮寫為?ptr

舉個例子:

package main

import "fmt"

func main() {
   var  ptr *int
   fmt.Printf("ptr 的值為 : %x\n", ptr) // ptr 的值為 : 0
}

空指針判斷:

package main

import "fmt"

func main() {
    var ptr *string
    fmt.Println(ptr)
    fmt.Printf("ptr的值是%v\n", ptr)
    
    if ptr != nil {
        fmt.Println("非空")
    } 
    if ptr == nil {
        fmt.Println("空值")
    }
}

5. make

make?是用于初始化內置的數據結構,比如?slicemap?和?channel

func make(t Type, size ...IntegerType) Type

舉個例子:

package main

import "fmt"

func main() {
    var user map[string]int
    user = make(map[string]int, 10)
    user["age"] = 18
    fmt.Println(user)

    /** 
        slice := make([]int, 0, 100)
        hash := make(map[int]bool, 10)
        ch := make(chan int, 5)
    **/
}

6. new

new?的作用是根據傳入的類型分配一片內存空間并返回指向這片內存空間的指針。

func new(Type) *Type

解釋一下:

  • Type 表示類型,new 函數只接受一個參數,這個參數是一個類型
  • *Type 表示類型指針,new 函數返回一個指向該類型內存地址的指針

舉個例子:

package main

import "fmt"

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
}

7. make 和 new 的區別

面試高頻題,這個要考,記一下。

  • make 和 new 都是用來做內存分配
  • make 只用于 slice、map 、channel 的初始化,返回的還是這三個引用類型本身,因為這三種類型就是引用類型,所以就沒必要返回其指針了
  • new 用于類型的內存分配,并且內存對應的值為類型零值,返回的是指向類型的指針。

8. 問題

Q:?執行下面的代碼會出現啥問題?

package main

import "fmt"

func main() {
    var a *int
    *a = 100
    fmt.Println(*a)

    var user map[string]int
    user["age"] = 18
    fmt.Println(user)
}

A:?會出現?panic runtime error: invalid memory address or nil pointer dereference。出錯行數在第 7 行。

原因:在 Go 語言中我們使用引用類型的變量需要先申明、分配內存空間,否則在賦值是會出錯。值類型的變量除外,因為其在申明時就分配了默認的內存空間。這也是 new 和 make 的作用。

原文鏈接:https://segmentfault.com/a/1190000043187142

欄目分類
最近更新