日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参

發布時間:2023/11/27 生活经验 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 復合數據類型

Go 語言基本的復合數據類型有指針、數組、切片、字典、通道、結構和接口等。格式如下:

* pointerType	//	指針類型, 
[n]elementType	//	數組類型,
[]elementType	//	切片類型,
map [keyType]valueType	//	字典類型
chan valueType	//	通道類型//	結構體類型
struct {fieldType fieldTypefieldType fieldType...
}//	接口類型
interface {method1(inputParams) (returnParams)method2(inputParams) (returnParams)...
}

2. 指針定義

每個變量在運行時都擁有一個地址,這個地址代表變量在內存中的位置。Go 語言中使用在變量名前面添加&操作符(前綴)來獲取變量的內存地址(取地址操作),格式如下:

ptr := &v    // v 的類型為 T

其中 v 代表被取地址的變量,變量 v 的地址使用變量 ptr 進行接收, ptr 的類型為*T,稱做 T 的指針類型,*代表指針。

Go 語言的取地址符是 &放到一個變量前使用就會返回相應變量的內存地址。
獲取變量在內存中地址:

package mainimport "fmt"func main() {var a int = 10fmt.Printf("變量的地址: %x\n", &a) // 變量的地址: c000018068fmt.Printf("%p", &a)          // %p 打印變量內存地址,指針的值是帶有0x十六進制前綴的一組數據。
}

一個指針變量指向了一個值的內存地址。在使用指針前你需要聲明指針。指針聲明格式如下:

var varName *varType

varType 為指針類型, varName 為指針變量名, * 號用于指定變量是作為一個指針。以下是有效的指針聲明:

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮點型 */

Go 同樣支持多級指針,類似 **ip

一個指針變量可以指向任何一個值的內存地址,它所指向的值的內存地址在 32 和 64 位機器上分別占用 4 或 8 個字節,占用字節的大小與所指向的值的大小無關。

當一個指針被定義后沒有分配到任何變量時,它的默認值為 nil 。指針變量通常縮寫為 ptr

變量、指針和地址三者的關系是,每個變量都擁有地址,指針的值就是地址。

3. 指針使用

指針使用流程:

  • 定義指針變量
  • 為指針變量賦值
  • 訪問指針變量中指向地址的值

在指針類型前面加上 * 號(前綴)來獲取指針所指向的內容。

使用示例:

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

輸出結果為:

a 變量的地址是: 20818a220
ip 變量儲存的指針地址: 20818a220
*ip 變量的值: 20

以下幾點使用指針的建議:

  • 不要對 mapslicechannel 這類引用類型使用指針;

  • 如果需要修改方法接收者內部的數據或者狀態時,需要使用指針;

  • 如果需要修改參數的值或者內部數據時,也需要使用指針類型的參數;

  • 如果是比較大的結構體,每次參數傳遞或者調用方法都要內存拷貝,內存占用多,這時候可以考慮使用指針;

  • intbool 這樣的小數據類型沒必要使用指針;

  • 如果需要并發安全,則盡可能地不要使用指針,使用指針一定要保證并發安全;

  • 指針最好不要嵌套,也就是不要使用一個指向指針的指針,雖然 Go 語言允許這么做,但是這會使你的代碼變得異常復雜;

4. 指針特點

  1. 在賦值語句中,*p 出現在 = 左邊表示是指針聲明,*p 出現在 = 右邊表示取指針指向的值;

  2. 結構體指針訪問結構體字段仍然使用 . 點操作符, Go 不支持 -> 操作符;

  3. Go 不支持指針的運算;

  4. 函數中允許返回變量的地址;

package mainimport "fmt"// Phone is struct type 注釋開頭必須是 結構體或者方法的名字,后面再加空格
type Phone struct { //exported type Phone should have comment or be unexportedgo-lintmodel stringcolor stringprice int
}func main() {var a *int = nilvar b *intc := 10b = &ce := *bphone := Phone{"huawei", "blue", 1000}p := &phone// p++  invalid operation: p++ (non-numeric type *Phone)fmt.Printf("a is %v, a type is %T\n", a, a)fmt.Printf("b is %v, b type is %T\n", b, b)fmt.Printf("e is %v, e type is %T\n", e, e)fmt.Printf("p is %v, p type is %T\n", p, p)fmt.Printf("p.model is %v, p.price is %v\n", p.model, p.price)result := sum(5, 3)fmt.Printf("result is %v, result type is %T\n", *result, result)}func sum(a, b int) *int {ret := a + breturn &ret
}

輸出結果:

a is <nil>, a type is *int
b is 0xc000016068, b type is *int
e is 10, e type is int
p is &{huawei blue 1000}, p type is *main.Phone
p.model is huawei, p.price is 1000
result is 8, result type is *int
  1. 對變量進行取地址操作使用 &操作符,可以獲得這個變量的指針變量;

  2. 對指針變量進行取值操作使用 *操作符,可以獲得指針變量指向的原變量的值;

5. Go 空指針

當一個指針被定義后沒有分配到任何變量時,它的值為 nilnil 指針也稱為空指針。 nil 在概念上和其它語言的 nullNonenilNULL 一樣,都指代零值或空值。

空指針值為 nil,即沒有內存地址,是不能進行賦值操作的,比如下面的示例:

var intP *int
*intP =10

運行的時候會提示 invalid memory address or nil pointer dereference。這時候該怎么辦呢?其實只需要通過 new 函數給它分配一塊內存就可以了,如下所示:

var intP *int = new(int)
//更推薦簡短聲明法,這里是為了演示
//intP:=new(int)

一個指針變量通常縮寫為 ptr 。空指針判斷方法:

if(ptr != nil)     /* ptr 不是空指針 */
if(ptr == nil)    /* ptr 是空指針 */

使用示例:

package mainimport "fmt"func main() {var  ptr *intfmt.Printf("ptr 的值為 : %x\n", ptr  )
}

輸出結果為:

ptr 的值為 : 0

6. Go 指針數組

ptr 為整型指針數組。因此每個元素都指向了一個值。以下實例的三個整數將存儲在指針數組中:

package mainimport "fmt"const MAX int = 3func main() {a := []int{10,100,200}var i intvar ptr [MAX]*int;       // 聲明了整型指針數組for  i = 0; i < MAX; i++ {ptr[i] = &a[i] /* 整數地址賦值給指針數組 */}for  i = 0; i < MAX; i++ {fmt.Printf("a[%d] = %d\n", i,*ptr[i] )}
}

7. Go 指向指針的指針

如果一個指針變量存放的又是另一個指針變量的地址,則稱這個指針變量為指向指針的指針變量。當定義一個指向指針的指針變量時,第一個指針存放第二個指針的地址,第二個指針存放變量的地址:

訪問指向指針的指針變量值需要使用兩個 * 號,如下所示:

package mainimport "fmt"func main() {var a intvar ptr *intvar pptr **inta = 3000/* 指針 ptr 地址 */ptr = &a/* 指向指針 ptr 地址 */pptr = &ptr/* 獲取 pptr 的值 */fmt.Printf("變量 a = %d\n", a )fmt.Printf("指針變量 *ptr = %d\n", *ptr )fmt.Printf("指向指針的指針變量 **pptr = %d\n", **pptr)
}

8. Go 指針作為函數參數

Go 語言允許向函數傳遞指針,只需要在函數定義的參數上設置為指針類型即可。

ackage mainimport "fmt"func main() {/* 定義局部變量 */var a int = 100var b int= 200fmt.Printf("交換前 a 的值 : %d\n", a )fmt.Printf("交換前 b 的值 : %d\n", b )/* 調用函數用于交換值* &a 指向 a 變量的地址* &b 指向 b 變量的地址*/swap(&a, &b);fmt.Printf("交換后 a 的值 : %d\n", a )fmt.Printf("交換后 b 的值 : %d\n", b )
}func swap(x *int, y *int) {var temp inttemp = *x    /* 保存 x 地址的值 */*x = *y      /* 將 y 賦值給 x */*y = temp    /* 將 temp 賦值給 y */
}

總結

以上是生活随笔為你收集整理的Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。