1. 程式人生 > >Golang系列(五)之Golang指標

Golang系列(五)之Golang指標

1. 指標的概念

概念 說明
變數 是一種佔位符,用於引用計算機的記憶體地址。可理解為記憶體地址的標籤
指標 表示記憶體地址,表示地址的指向。指標是一個指向另一個變數記憶體地址的值
& 取地址符,例如:{指標}:=&{變數}
* 取值符,例如:{變數}:=*{指標}

2. 記憶體地址說明

2.1. 記憶體定義

計算機的記憶體 RAM 可以把它想象成一些有序的盒子,一個接一個的排成一排,每一個盒子或者單元格都被一個唯一的數字標記依次遞增,這個數字就是該單元格的地址,也就是記憶體的地址。
這裡寫圖片描述

硬體角度

:記憶體是CPU溝通的橋樑,程式執行在記憶體中。

邏輯角度:記憶體是一塊具備隨機訪問能力,支援讀寫操作,用來存放程式及程式執行中產生的資料的區域。

概念 比喻
記憶體 一層樓層
記憶體塊 樓層中的一個房間
變數名 房間的標籤,例如:總經理室
指標 房間的具體地址(門牌號),例如:總經理室地址是2樓201室
變數值 房間裡的具體儲存物
指標地址 指標的地址:儲存指標記憶體塊的地址

2.2. 記憶體單位和編址

2.2.1. 記憶體單位

單位 說明
位(bit) 計算機中最小的資料單位,每一位的狀態只能是0或1
位元組(Byte) 1Byte=8bit,是記憶體基本的計量單位
“字”由若干個位元組構成,字的位數叫字長,不同檔次的機器有不同的字長
KB 1KB=1024Byte,即1024個位元組
MB 1MB=1024KB
GB 1GB=1024MB

2.2.2. 記憶體編址

計算機中的記憶體按位元組編址,每個地址的儲存單元可以存放一個位元組的資料,CPU通過記憶體地址獲取指令和資料,並不關心這個地址所代表的空間在什麼位置,記憶體地址和地址指向的空間共同構成了一個記憶體單元。

2.2.3. 記憶體地址

記憶體地址通常用16進位制的資料表示,例如0x0ffc1。

3.變數與指標運算理解

編寫一段程式,檢索出值並存儲在地址為 200 的一個塊記憶體中,將其乘以 3,並將結果儲存在地址為 201 的另一塊記憶體中

3.1.本質

  1. 檢索出記憶體地址為 200 的值,並將其儲存在 CPU 中
  2. 將儲存在 CPU 中的值乘以 3
  3. 將 CPU 中儲存的結果,寫入地址為 201 的記憶體塊中

這裡寫圖片描述

3.2.基於變數的理解

  1. 獲取變數 a 中儲存的值,並將其儲存在 CPU 中
  2. 將其乘以 3
  3. 將結果儲存在變數 b 中

這裡寫圖片描述

var a = 6 
var b = a * 3

3.3.基於指標的理解

func main() {
    a := 200
    b := &a
    *b++
    fmt.Println(a)
}

以上函式對a進行+1操作,具體理解如下:

1.a:=200

這裡寫圖片描述

2. b := &a

這裡寫圖片描述

3. *b++

這裡寫圖片描述

這裡寫圖片描述

4. 指標的使用

4.1. 方法中的指標

方法即為有接受者的函式,接受者可以是型別的例項變數或者是型別的例項指標變數。但兩種效果不同。

1、型別的例項變數

func main(){
    person := Person{"vanyar", 21}
    fmt.Printf("person<%s:%d>\n", person.name, person.age)
    person.sayHi()
    person.ModifyAge(210)
    person.sayHi()
}
type Person struct {
    name string
    age int
}
func (p Person) sayHi() {
    fmt.Printf("SayHi -- This is %s, my age is %d\n",p.name, p.age)
}
func (p Person) ModifyAge(age int) {
    fmt.Printf("ModifyAge")
    p.age = age
}


//輸出結果
person<vanyar:21>
SayHi -- This is vanyar, my age is 21
ModifyAgeSayHi -- This is vanyar, my age is 21

儘管 ModifyAge 方法修改了其age欄位,可是方法裡的p是person變數的一個副本,修改的只是副本的值。下一次呼叫sayHi方法的時候,還是person的副本,因此修改方法並不會生效。

即例項變數的方式並不會改變接受者本身的值。

2、型別的例項指標變數

func (p *Person) ChangeAge(age int)  {
    fmt.Printf("ModifyAge")
    p.age = age
}

Go會根據Person的示例型別,轉換成指標型別再拷貝,即 person.ChangeAge會變成 (&person).ChangeAge。

指標型別的接受者,如果例項物件是值,那麼go會轉換成指標,然後再拷貝,如果本身就是指標物件,那麼就直接拷貝指標例項。因為指標都指向一處值,就能修改物件了。

5. 零值與nil(空指標)

變數宣告而沒有賦值,預設為零值,不同型別零值不同,例如字串零值為空字串;

指標宣告而沒有賦值,預設為nil,即該指標沒有任何指向。當指標沒有指向的時候,不能對(*point)進行操作包括讀取,否則會報空指標異常。

func main(){
    // 宣告一個指標變數 aPot 其型別也是 string
    var aPot *string
    fmt.Printf("aPot: %p %#v\n", &aPot, aPot) // 輸出 aPot: 0xc42000c030 (*string)(nil)
    *aPot = "This is a Pointer"  // 報錯: panic: runtime error: invalid memory address or nil pointer dereference
}

解決方法即給該指標分配一個指向,即初始化一個記憶體,並把該記憶體地址賦予指標變數,例如:

// 宣告一個指標變數 aPot 其型別也是 string
    var aPot *string
    fmt.Printf("aPot: %p %#v\n", &aPot, aPot) // 輸出 aPot: 0xc42000c030 (*string)(nil)

    aPot = &aVar
    *aPot = "This is a Pointer"
    fmt.Printf("aVar: %p %#v \n", &aVar, aVar) // 輸出 aVar: 0xc42000e240 "This is a Pointer"
    fmt.Printf("aPot: %p %#v %#v \n", &aPot, aPot, *aPot) // 輸出 aPot: 0xc42000c030 (*string)(0xc42000e240) "This is a Pointer"

或者通過new開闢一個記憶體,並返回這個記憶體的地址。

var aNewPot *int

aNewPot = new(int)
*aNewPot = 217
fmt.Printf("aNewPot: %p %#v %#v \n", &aNewPot, aNewPot, *aNewPot) // 輸出 aNewPot: 0xc42007a028 (*int)(0xc42006e1f0) 217

6. 總結

  • Golang提供了指標用於操作資料記憶體,並通過引用來修改變數。
  • 只宣告未賦值的變數,golang都會自動為其初始化為零值,基礎資料型別的零值比較簡單,引用型別和指標的零值都為nil,nil型別不能直接賦值,因此需要通過new開闢一個記憶體,或者通過make初始化資料型別,或者兩者配合,然後才能賦值。
  • 指標也是一種型別,不同於一般型別,指標的值是地址,這個地址指向其他的記憶體,通過指標可以讀取其所指向的地址所儲存的值。
  • 函式方法的接受者,也可以是指標變數。無論普通接受者還是指標接受者都會被拷貝傳入方法中,不同在於拷貝的指標,其指向的地方都一樣,只是其自身的地址不一樣。

相關推薦

Golang系列Golang指標

1. 指標的概念 概念 說明 變數 是一種佔位符,用於引用計算機的記憶體地址。可理解為記憶體地址的標籤 指標 表示記憶體地址,表示地址的指向。指標是一個指向另一個變數記憶體地址的值 & 取地址符,

Golang系列面向物件程式設計

面向物件程式設計:       把一組資料結構和處理它們的方法組成物件(object),把相同行為的物件歸納為類(class),通過類的封裝(encapsulation)隱藏內部細節,通過繼承(inheritance)實現類的特化(specialization)[方法的重寫,

Golang系列基礎篇

一、初識Go語言(一)概述一個在語言層面實現了併發機制的類C通用型程式語言。(二)Go關鍵字(25個)類別關鍵字說明程式宣告package,import包的宣告和匯入宣告與定義var,const變數和常量的宣告type用於定義型別複合資料型別struct定義結構體,類似java中的classinterface

【轉】Spring MVC系列自定義數據綁定---HandlerMethodArgumentResolver

開閉 src pat 獲取參數 mvc .net 定義 開閉原則 淺析 介紹 前面幾節我們介紹了Spring MVC的幾種常見的數據綁定的方法,可以靈活地獲取用戶請求中的參數,例如@PathVariable,@ModelAttribute,@RequestPar

Mysql資料庫優化系列------索引優化策略面試題

實驗: Type:range   此處使用上了範圍索引 Key_len:12/3=4列 使用到了索引c1,c2,c3,c4.解析:因為order by c3是有序的,所以c3,c4也用到了索引 上圖用到了c1,c2,c3,order by有序,可以利用索引。 上圖

程式設計師網路安全系列:數字證書以及12306的證書問題

系列目錄: 前文回顧 假如,明明和麗麗相互不認識,明明想給麗麗寫一封情書,讓隔壁老王送去 如何保證隔壁老王不能看到情書內容?(保密性) 如何保證隔壁老王不修改情書的內容?(完整性) 如何保證隔壁老王不冒充明明?(身份認證) 如何保證明明不能否認情書是自己寫的?(來源的不可否認) 中間人攻擊 上面

重學Golang系列: 深入理解 interface和reflect

前言 interface(即介面),是Go語言中一個重要的概念和知識點,而功能強大的reflect正是基於interface。本文即是對Go語言中的interface和reflect基礎概念和用法的一次梳理,也算是我階段學習的總結,以期溫故而知新。 interface(介面) 定義 在Go語言中,如果自定義型

資料探勘入門系列教程Apriori演算法Python實現

資料探勘入門系列教程(五)之Apriori演算法Python實現載入資料集獲得訓練集頻繁項的生成生成規則獲得support獲得confidence獲得Lift進行驗證總結參考 資料探勘入門系列教程(五)之Apriori演算法Python實現 在上一篇部落格中,我們介紹了Apriori演算法的演算法流

python系列centos6.x中部署多個python版本

python pyenv centos6.x virtualenv 博主QQ:819594300博客地址:http://zpf666.blog.51cto.com/有什麽疑問的朋友可以聯系博主,博主會幫你們解答,謝謝支持!使用pyenv+virtualenv方式部署python多版本pyenv

bfzwjeqjSpriNgMc學習系列3url

ref htm 學習 pri blank url lan get 系列 bfzwjeqjSpriNgMc學習系列(3)之url χ絳 bfzwjeqjSpriNgMc學習系列(3)之urlbfzwjeqjSpriNgMc學習系列(3)之url

python爬蟲從入門到放棄 正則的基本使用

語言 代碼例子 name 添加 iter ima 制表符 imp things 什麽是正則表達式 正則表達式是對字符串操作的一種邏輯公式,就是 事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規則字符”,這個“規則字符” 來表達對字符的一種過濾邏輯。 正則並不是

mysql基礎pymysql

none set python 導入 char span import mysql pre pymysql模塊: pip3 install pymysql -i https://pypi.douban.com/simple Python模塊:對數據庫進行

源碼分析系列x264_ratecontrol_dataflow

技術 stc 碼率控制 碼率 targe article nbsp target 緩沖區 http://www.cnblogs.com/xkfz007/articles/2616159.html 碼率控制部分關鍵函數 5.1 x264_ratecontrol_star

Windows Server 2012單林、多樹、多站點AD 部署系列創建樹域

windows server 域 樹域 站點 多域環境 本章博文開始在BJ、SH、GZ站點為林bicionline.org 創建樹域控及調配的相關DNS等功能。網絡配置:1、為BJ站點ds04、SH站點pdc02和GZ站點ad02配置網絡, IP配置分別如下:(註:在創建域樹環境時,確

PHP系列PHP字符串處理

php字符串處理 php字符串處理1、字符串的處理方式(分割匹配找查替換)//聲明一個關聯數組,數組名為$lamp, 成員有4個$lamp = array( ‘os‘=>‘Linux‘,‘webserver‘ =>‘Apache‘, ‘db‘=>‘MySQL‘, ‘language‘=>

MavenMaven配置阿裏雲鏡像飛快下jar包

png 技術分享 jar包 世界 包導入 ont 全世界 需要 XML 用過Maven的人都知道Maven對於依賴的管理讓我們程序員從此遠離了自己去在項目中把需要的jar包導入到項目中,但是因為中央倉庫是在國外的,所以在我們從中央倉庫下載依賴的時候, 我們發現下載速度真的

JavaWebJSTL標簽庫

ron 數據庫連接 導入jar 作用域 .text 字符串操作 p標簽 異常 讀取 前言   前面介紹了EL表達式,其實EL表達式基本上是和JSTL核心標簽庫搭配一起使用才能發揮效果的。接下來讓我們一起來認識一下吧!   在之前我們學過在JSP頁面上為了不使用腳本,所以

Python操作rabbitmq系列:根據主題分配消息

method type 同時 elephant com .info err 現在 bin 接著上一章,使用exchange_type=‘direct‘進行消息傳遞。這樣消息會完全匹配後發送到對應的接收端。現在我們想幹這樣一件事: C1獲取消息中包含:orange內容的消息,

Java常用類集合工具類Collections

可變集合 並發 nts oid element 出現的次數 ole 最小 概述 前言    Java提供了一個操作Set、List和Map等集合的工具類:Collections,該工具類提供了大量方法對集合進行排序、查詢和修改等操作,     還提供了將集合對象置為不可

Vue入門系列Vue實例詳解與生命周期

auto res context mode parent all from bool silent 【入門系列】 【本文轉自】   http://www.cnblogs.com/fly_dragon Vue的實例是Vue框架的入口,其實也就是前端的ViewM