介紹:
? ? ? ? 指針式一種數據類型,用來存儲值的內存地址,為了便于理解,我們也可以把指針未內存地址,指針類型只占用內存4個或 8 個字節,在Golang 語言中,類型名稱加 *? 表示改類型的指針類型。
? ? ? ? 指針類型變量也需要一塊內存空間儲存值,指針變量的值就是它所指向數據的內存地址,而普通變量的值就是具體存放的數據,不同的指針類型變量之間無法互相賦值,在Golang 語言,指針不支持運算,也不能獲取常量的指針
指針定義:
? ? ? ? 在Golang 語言中,指針定義有3中方式:
? ? ? ? 第一種方式是使用取地符 & 獲取變量的指針(內存地址);
? ? ? ? 第二種方式的使用var 關鍵字聲明指針變量,使用var 關鍵字聲明的變量不能直接賦值和取值,因為它還沒有內存地址,它的值是nil;
? ? ? ? 第三種方式是使用內置的new 函數來聲明指針的變量,new 函數接收一個參數,可以傳遞類型給它,返回值是傳遞類型的指針類型。
實例代碼:
func main() {a := 1p := &afmt.Println("變量a 的值為:", a)fmt.Println("變量a 的內存地址為:", p)fmt.Printf("變量a 的類型為 %T\n:", a)fmt.Printf("變量a 的類型為 %T\n:", p)//var str string//var p1 *int////p1 = &str////p2 := new(int)//fmt.Printf("%v %T\n",p2,p2)
}
?輸出結果:
指針操作:
? ? ? ? 在Golang 語言中,指針操作包括取值和修改,取值就是獲取指針指向的值,只需在指針變量前加 * ;修改就是修改指針指向的值,需要注意的是使用 var 關鍵字聲明的指針變量不能直接賦值和取值,因為它還沒有它分配內存,它的值為nil ,可以使用內置函數 new 給它分配內存。
示例代碼:
import "fmt"func main() {b := 2p3 := &bval := *p3fmt.Println("變量 val 的值為 ",val)*p3 = 3fmt.Println("*p3 指針指向的值為: ", *p3)fmt.Println("變量 b 的值為: ",b)var p4 *int = new(int)*p4 = 4fmt.Println(*p4)
}
執行結果:
指針應用:
? ? ? ? 在Golang 語言中,函數傳遞參數只有值傳遞,傳遞的實參都是參數原始值的拷貝副本,所以我們傳遞類型的參數時,修改參數的值,原始數據不會被修改。但是,如果是指針類型的參數,修改參數的值,原始數據也會被修改,原因的指針類型的參數存儲的事內存地址,并且和實參的內存地址相同。
示例代碼:
func main() {mySalary := 80000fmt.Printf("變量 mySalary 的內存地址為: %p\n",&mySalary)modifySalary(mySalary)fmt.Println(mySalary)// 指針類型參數,實參的值被改變modifySalary2(&mySalary)fmt.Println(mySalary)}func modifySalary(salary int) {fmt.Printf("參數變量的內存地址為: %p\n",&salary)salary = 100000
}func modifySalary2(salary *int) {fmt.Printf("參數變量的內存地址為: %p\n",&salary)*salary = 100000
}
運行結果:
指針接收者:
? ? ? ? 在Golang 語言中,定義一個方法,接收者可以的值類型和指針類型,二者都可以調用方法,因為Golang 編譯器會自動轉換,所以二者是等價的
? ? ? ? 示例代碼:
import "fmt"type worker struct {name stringsalary uint
}func (w *worker) raise() {w.salary += 1000
}func (w worker) raise1() {w.salary += 1000
}func main() {w := worker{name: "frank",salary: 5000,}// 指針類型接收者w.raise()fmt.Printf("w 的姓名是 %s,薪水是每月 %d\n", w.name, w.salary)// 值類型調用者w1 := worker{name: "frank1",salary: 5000,}fmt.Printf("w 的姓名是 %s,薪水是每月 %d\n", w1.name, w1.salary)w2 := worker{name: "luck",salary: 5000,}w2.raise()fmt.Printf("w 的姓名是 %s,薪水是每月 %d\n", w2.name, w2.salary)w3 := worker{name: "luck1",salary: 5000,}w3.raise()fmt.Printf("w 的姓名是 %s,薪水是每月 %d\n", w3.name, w3.salary)
}
運行結果:
如果需要修改接收者,可以使用指針修改指針向數據的值。
如果接收者是非 map 、slice 和 channel 類型,并且數據比較大,可以使用指針來節省內存。
總結:
? ? ? ? 本文我們介紹了Golang 語言中的指針,和指針定義與操作,并且介紹了指針為指針參數和指針接收者的應用區別。使用指針雖然可以修改數據的值和節省內存,但是也給開發帶來復雜性,所以為了開發簡單,在開發中處理必須使用指針類型外,盡量使用值類型,比如數據小的類型int? 、 bool 和需要并安全的代碼其實沒有必要使用指針。