亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

一文介紹Go語言中的指針

 更新時(shí)間:2023年10月07日 09:04:20   作者:賈維斯Echo  
指針是一個(gè)存儲(chǔ)變量?jī)?nèi)存地址的變量,本文主要介紹了Go語言中的指針,具有一定的參考價(jià)值,感興趣的可以了解一下

一、Go語言中的指針介紹

1.1 指針介紹

指針是一個(gè)存儲(chǔ)變量?jī)?nèi)存地址的變量。它們?cè)试S程序直接訪問和操作內(nèi)存中的數(shù)據(jù),而不是對(duì)數(shù)據(jù)的副本進(jìn)行操作。以下是指針的一些關(guān)鍵概念:

  • 內(nèi)存地址: 每個(gè)變量在計(jì)算機(jī)內(nèi)存中都有一個(gè)唯一的地址,指針存儲(chǔ)了這個(gè)地址。
  • 指針變量: 用于存儲(chǔ)其他變量地址的變量稱為指針變量。
  • 取地址操作符(&): 可以使用取地址操作符&來獲取變量的地址。
  • 解引用操作符(*): 可以使用解引用操作符*來訪問指針?biāo)赶虻淖兞康闹怠?/li>

Go語言中的值類型(int、float、bool、string、array、struct)都有對(duì)應(yīng)的指針類型,如:*int、*int64、*string等。

1.2 基本語法

  • var ptr *int: 聲明指針變量ptr,用于指向一個(gè)int類型變量的地址。
  • &a獲取變量a的內(nèi)存地址,返回一個(gè)指向該地址的指針。
  • *ptr: 讀取ptr指針指向地址的值,這個(gè)操作稱為“解引用”。
  • *ptr = 100: 將100賦值給ptr指向的變量。

1.3 聲明和初始化

在 Go 語言中,可以使用指針來引用任何類型的變量。指針的聲明和初始化可以通過如下語法完成:

var p *int  // 聲明一個(gè)指向 int 類型的指針 p
var str *string  // 聲明一個(gè)指向 string 類型的指針 str

初始化指針可以通過 new 函數(shù)來分配內(nèi)存并返回指針的地址:

p := new(int)  // 分配一個(gè) int 類型的內(nèi)存,并將指針 p 指向該內(nèi)存

示例代碼:

package main
 import "fmt"
 func main() {
     var p *int
     var str *string
     fmt.Printf("p: %v, str: %v\n", p, str) // 輸出 p: <nil>, str: <nil>
     x := 10
     p = &x // 將指針p指向變量x的地址
     fmt.Printf("p: %v\n", p)   // 輸出 p: 0xc0000100e0
     fmt.Printf("*p: %d\n", *p) // 輸出 *p: 10
     str = new(string) // 分配一個(gè)string類型的內(nèi)存,并將指針str指向該內(nèi)存
     fmt.Printf("str: %v\n", str)   // 輸出 str: 0xc000010120
     fmt.Printf("*str: %s\n", *str) // 輸出 *str: ""
     *str = "Hello, Go!" // 通過指針修改字符串的值
     fmt.Printf("*str: %s\n", *str) // 輸出 *str: Hello, Go!
 }

1.4 Go 指針的3個(gè)重要概念

1.4.1 指針地址(Pointer Address)

  • 在Go語言中,指針地址表示指針?biāo)赶虻淖兞炕驍?shù)據(jù)在內(nèi)存中的位置。
  • 在Go語言中,與C/C++等語言不同,您不能直接獲取指針的具體地址值,因?yàn)镚o語言為了安全性和內(nèi)存管理而采用了更抽象的設(shè)計(jì)。但是,您可以通過獲取變量的地址來創(chuàng)建和使用指針,而這個(gè)地址由Go語言自動(dòng)管理。

1.4.2 指針類型(Pointer Type)

  • Go語言的指針類型表示指針可以指向的數(shù)據(jù)類型。

1.4.3 指針取值(Pointer Dereferencing)

  • 指針取值是指通過指針來訪問其所指向的內(nèi)存位置上的數(shù)據(jù)。在Go語言中,要獲取指針?biāo)赶虻臄?shù)據(jù)的值,您需要使用解引用操作符 *。

1.5 獲取指針的地址和解引用

通過 & 操作符可以獲取變量的地址,例如:

func main() {
	a := 10
	b := &a  // 將指針 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的圖示:

使用*操作符可以解引用指針,獲取指針指向的值:

fmt.Println(*b)  // 輸出指針 b 指向的值,即變量 a 的值

示例代碼:

func main() {
	//指針取值
	a := 10
	b := &amp;a // 取變量a的地址,將指針保存到b中
	fmt.Printf("type of b:%T\n", b)
	c := *b // 指針取值(根據(jù)指針去內(nèi)存取值)
	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

總結(jié): 取地址操作符&和取值操作符*是一對(duì)互補(bǔ)操作符,&取出地址,*根據(jù)地址取出地址指向的值。

變量、指針地址、指針變量、取地址、取值的相互關(guān)系和特性如下:

  • 對(duì)變量進(jìn)行取地址(&)操作,可以獲得這個(gè)變量的指針變量。
  • 指針變量的值是指針地址。
  • 對(duì)指針變量進(jìn)行取值(*)操作,可以獲得指針變量指向的原變量的值。

1.6 傳遞指針給函數(shù)

您可以將指針作為參數(shù)傳遞給函數(shù),從而可以在函數(shù)內(nèi)部修改原始變量的值,而不是復(fù)制。這可以用于實(shí)現(xiàn)函數(shù)的副作用。

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
}

1.7 指針的比較

您可以使用==!=運(yùn)算符來比較指針。它們將比較指針是否引用相同的內(nèi)存地址。

var x int = 42
var p *int  // 聲明一個(gè)整數(shù)指針
p = &x      // 將變量x的地址分配給指針p
fmt.Println(p == &x) // true,p和&x都指向相同的內(nèi)存地址

1.8 指針的使用注意事項(xiàng)

  • 謹(jǐn)慎使用指針,以避免懸掛指針(dangling pointers)和內(nèi)存泄漏等問題。
  • 在Go中,指針通常用于傳遞大型數(shù)據(jù)結(jié)構(gòu),以避免復(fù)制數(shù)據(jù)。
  • Go沒有指針運(yùn)算(如C/C++中的指針?biāo)阈g(shù)運(yùn)算),因此您不能像C/C++那樣執(zhí)行指針加法和減法操作。

二、空指針和指針的零值

  • **指針的零值:**如果您聲明了一個(gè)指針但沒有初始化它,它將具有零值,即nil。
  • **空指針:**如果指針沒有指向任何有效的內(nèi)存地址,它將具有nil值,表示空指針。在使用指針之前,通常會(huì)檢查指針是否為nil。
package main
import "fmt"
func main() {
    var p *string
    fmt.Println(p)
    fmt.Printf("p的值是%s/n", p)
    if p != nil {
        fmt.Println("非空")
    } else {
        fmt.Println("空值")
    }
}

三、指針的應(yīng)用場(chǎng)景

3.1 傳遞大對(duì)象

在函數(shù)參數(shù)傳遞時(shí),如果直接傳遞大對(duì)象的副本,會(huì)產(chǎn)生額外的內(nèi)存開銷。通過傳遞指針,可以避免復(fù)制整個(gè)對(duì)象,提高程序的性能。

示例代碼:

 package main
 import "fmt"
 type BigObject struct {
     // 大對(duì)象的定義...
 }
 func processObject(obj *BigObject) {
     // 對(duì)大對(duì)象進(jìn)行處理...
 }
 func main() {
     obj := BigObject{}
     processObject(&obj) // 傳遞大對(duì)象的指針
 }

3.2 指針作為函數(shù)參數(shù)和修改函數(shù)外部變量

在 Go 語言中,函數(shù)的參數(shù)傳遞默認(rèn)是值傳遞。通過指針傳遞,函數(shù)可以修改函數(shù)外部的變量。這在需要修改外部變量的值時(shí)非常有用,特別是在處理復(fù)雜數(shù)據(jù)結(jié)構(gòu)或需要對(duì)全局狀態(tài)進(jìn)行修改的情況下。

示例代碼:

 package main
 import "fmt"
 func modifyValue(ptr *int) {
     *ptr = 30 // 修改指針指向的值
 }
 func main() {
     x := 10
     modifyValue(&x) // 傳遞x的地址給modifyValue函數(shù)
     fmt.Println(x) // 輸出修改后的x的值,即30
 }

3.3 動(dòng)態(tài)分配內(nèi)存

指針的另一個(gè)重要應(yīng)用是動(dòng)態(tài)分配內(nèi)存。通過 new 函數(shù)可以在堆上動(dòng)態(tài)分配內(nèi)存,避免了在棧上分配固定大小的內(nèi)存空間的限制。這對(duì)于需要返回動(dòng)態(tài)分配的數(shù)據(jù)或創(chuàng)建復(fù)雜數(shù)據(jù)結(jié)構(gòu)非常有用。

示例代碼:

 package main
 import "fmt"
 type ComplexStruct struct {
     // 復(fù)雜數(shù)據(jù)結(jié)構(gòu)的定義...
 }
 func createComplexStruct() *ComplexStruct {
     cs := new(ComplexStruct) // 動(dòng)態(tài)分配內(nèi)存并返回指針
     // 初始化復(fù)雜數(shù)據(jù)結(jié)構(gòu)...
     return cs
 }
 func main() {
     obj := createComplexStruct()
     // 對(duì)動(dòng)態(tài)分配的數(shù)據(jù)結(jié)構(gòu)進(jìn)行操作...
 }

3.4 函數(shù)返回指針

在函數(shù)中返回指針可以將函數(shù)內(nèi)部創(chuàng)建的變量的地址傳遞給調(diào)用者。這樣做可以避免復(fù)制整個(gè)變量,并允許調(diào)用者直接訪問和修改函數(shù)內(nèi)部的數(shù)據(jù)。

示例代碼:

 package main
 import "fmt"
 func createValue() *int {
     x := 10 // 在函數(shù)內(nèi)部創(chuàng)建變量
     return &x // 返回變量的地址
 }
 func main() {
     p := createValue()
     fmt.Println(*p) // 輸出通過指針訪問的函數(shù)內(nèi)部變量的值,即10
 }

四、new和make

我們先來看一個(gè)例子:

func main() {
	var a *int
	*a = 100
	fmt.Println(*a)
	var b map[string]int
	b["測(cè)試"] = 100
	fmt.Println(b)
}

執(zhí)行上面的代碼會(huì)引發(fā)panic,為什么呢? 在Go語言中對(duì)于引用類型的變量,我們?cè)谑褂玫臅r(shí)候不僅要聲明它,還要為它分配內(nèi)存空間,否則我們的值就沒辦法存儲(chǔ)。而對(duì)于值類型的聲明不需要分配內(nèi)存空間,是因?yàn)樗鼈冊(cè)诼暶鞯臅r(shí)候已經(jīng)默認(rèn)分配好了內(nèi)存空間。要分配內(nèi)存,就引出來今天的new和make。 Go語言中new和make是內(nèi)建的兩個(gè)函數(shù),主要用來分配內(nèi)存。

4.1 new

new是一個(gè)內(nèi)置的函數(shù),它的函數(shù)簽名如下:

func new(Type) *Type

其中,

  • Type表示類型,new函數(shù)只接受一個(gè)參數(shù),這個(gè)參數(shù)是一個(gè)類型
  • *Type表示類型指針,new函數(shù)返回一個(gè)指向該類型內(nèi)存地址的指針。

new函數(shù)不太常用,使用new函數(shù)得到的是一個(gè)類型的指針,并且該指針對(duì)應(yīng)的值為該類型的零值。舉個(gè)例子:

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
}

本節(jié)開始的示例代碼中var a *int只是聲明了一個(gè)指針變量a但是沒有初始化,指針作為引用類型需要初始化后才會(huì)擁有內(nèi)存空間,才可以給它賦值。應(yīng)該按照如下方式使用內(nèi)置的new函數(shù)對(duì)a進(jìn)行初始化之后就可以正常對(duì)其賦值了:

func main() {
	var a *int
	a = new(int)
	*a = 10
	fmt.Println(*a)
}

4.2 make

make也是用于內(nèi)存分配的,區(qū)別于new,它只用于slice、map以及channel的內(nèi)存創(chuàng)建,而且它返回的類型就是這三個(gè)類型本身,而不是他們的指針類型,因?yàn)檫@三種類型就是引用類型,所以就沒有必要返回他們的指針了。make函數(shù)的函數(shù)簽名如下:

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

make函數(shù)是無可替代的,我們?cè)谑褂胹lice、map以及channel的時(shí)候,都需要使用make進(jìn)行初始化,然后才可以對(duì)它們進(jìn)行操作。這個(gè)我們?cè)谏弦徽轮卸加姓f明,關(guān)于channel我們會(huì)在后續(xù)的章節(jié)詳細(xì)說明。

本節(jié)開始的示例中var b map[string]int只是聲明變量b是一個(gè)map類型的變量,需要像下面的示例代碼一樣使用make函數(shù)進(jìn)行初始化操作之后,才能對(duì)其進(jìn)行鍵值對(duì)賦值:

func main() {
    var b map[string]int
    b = make(map[string]int, 10)
    b["測(cè)試"] = 100
    fmt.Println(b)
}

4.3 new與make的區(qū)別

  • 二者都是用來做內(nèi)存分配的。
  • make只用于slice、map以及channel的初始化,返回的還是這三個(gè)引用類型本身;
  • 而new用于類型的內(nèi)存分配,并且內(nèi)存對(duì)應(yīng)的值為類型零值,返回的是指向類型的指針。

到此這篇關(guān)于一文介紹Go語言中的指針的文章就介紹到這了,更多相關(guān)Go 指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • go格式“占位符”輸入輸出 類似python的input

    go格式“占位符”輸入輸出 類似python的input

    這篇文章主要介紹了go格式“占位符”, 輸入輸出,類似python的input,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-04-04
  • 在Colaboratory上運(yùn)行Go程序的詳細(xì)過程

    在Colaboratory上運(yùn)行Go程序的詳細(xì)過程

    這篇文章主要介紹了在Colaboratory上運(yùn)行Go程序,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • golang中的struct操作

    golang中的struct操作

    結(jié)構(gòu)體是一種聚合的數(shù)據(jù)類型,是由零個(gè)或多個(gè)任意類型的值聚合成的實(shí)體,每個(gè)值稱為結(jié)構(gòu)體的成員。下面介紹下golang中的struct,感興趣的朋友一起看看吧
    2021-11-11
  • go?proto編譯引用外部包問題解決方案示例

    go?proto編譯引用外部包問題解決方案示例

    這篇文章主要為大家介紹了go?proto編譯引用外部包問題解決方案示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • go mod私有倉(cāng)庫(kù)配置小結(jié)

    go mod私有倉(cāng)庫(kù)配置小結(jié)

    Go語言私有倉(cāng)庫(kù)通常指的是那些不在公共倉(cāng)庫(kù)如GitHub上的倉(cāng)庫(kù),本文主要介紹了go mod私有倉(cāng)庫(kù)配置,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-03-03
  • 一文搞懂Golang?值傳遞還是引用傳遞

    一文搞懂Golang?值傳遞還是引用傳遞

    最多人犯迷糊的就是?slice、map、chan?等類型,都會(huì)認(rèn)為是?“引用傳遞”,從而認(rèn)為?Go?語言的?xxx?就是引用傳遞。正因?yàn)樗鼈冞€引用類型(指針、map、slice、chan等這些),這樣就可以修改原內(nèi)容數(shù)據(jù),這篇文章主要介紹了Golang?值傳遞還是引用傳遞,需要的朋友可以參考下
    2023-01-01
  • Go實(shí)現(xiàn)set類型的示例代碼

    Go實(shí)現(xiàn)set類型的示例代碼

    本文主要介紹了Go實(shí)現(xiàn)set類型的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • go 生成器模式的具體使用

    go 生成器模式的具體使用

    生成器是一種創(chuàng)建型設(shè)計(jì)模式,使你能夠分步驟創(chuàng)建復(fù)雜對(duì)象,本文主要介紹了go生成器模式的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • 一文帶你了解Go語言中方法的調(diào)用

    一文帶你了解Go語言中方法的調(diào)用

    這篇文章主要和大家分享一下Go語言中的方法的調(diào)用,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語言有一定的幫助,需要的小伙伴可以參考一下
    2022-12-12
  • Go中sync.Once源碼的深度講解

    Go中sync.Once源碼的深度講解

    sync.Once是Go語言標(biāo)準(zhǔn)庫(kù)中的一個(gè)同步原語,用于確保某個(gè)操作只執(zhí)行一次,本文將從源碼出發(fā)為大家詳細(xì)介紹一下sync.Once的具體使用,x希望對(duì)大家有所幫助
    2025-01-01

最新評(píng)論