新聞中心
go語(yǔ)言中全局變量和局部變量的區(qū)別
局部變量

我們提供的服務(wù)有:網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、銀州ssl等。為成百上千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的銀州網(wǎng)站制作公司
在函數(shù)體內(nèi)聲明的變量稱之為局部變量,它們的作用域只在函數(shù)體內(nèi),參數(shù)和返回值變量也是局部變量。
以下實(shí)例中 main() 函數(shù)使用了局部變量 a, b, c:
package main
import "fmt"
func main() {
/* 聲明局部變量 */
var a, b, c int
/* 初始化參數(shù) */
a = 10
b = 20
c = a + b
fmt.Printf ("結(jié)果: a = %d, b = %d and c = %d\n", a, b, c)
}
以上實(shí)例執(zhí)行輸出結(jié)果為:
結(jié)果: a = 10, b = 20 and c = 30
全局變量
在函數(shù)體外聲明的變量稱之為全局變量,全局變量可以在整個(gè)包甚至外部包(被導(dǎo)出后)使用。
全局變量可以在任何函數(shù)中使用,以下實(shí)例演示了如何使用全局變量:
package main
import "fmt"
/* 聲明全局變量 */
var g int
func main() {
/* 聲明局部變量 */
var a, b int
/* 初始化參數(shù) */
a = 10
b = 20
g = a + b
fmt.Printf("結(jié)果: a = %d, b = %d and g = %d\n", a, b, g)
}
以上實(shí)例執(zhí)行輸出結(jié)果為:
結(jié)果: a = 10, b = 20 and g = 30
Go 語(yǔ)言程序中全局變量與局部變量名稱可以相同,但是函數(shù)內(nèi)的局部變量會(huì)被優(yōu)先考慮。實(shí)例如下:
package main
import "fmt"
/* 聲明全局變量 */
var g int = 20
func main() {
/* 聲明局部變量 */
var g int = 10
fmt.Printf ("結(jié)果: g = %d\n", g)
}
以上實(shí)例執(zhí)行輸出結(jié)果為:
結(jié)果: g = 10
golang 方法返回的結(jié)構(gòu)體為什么取不到地址?
golang方法(method)返回值提取結(jié)構(gòu)體(struct)取不到地址的原因是,①返回值并沒(méi)有保存到變量中,返回值本身只是臨時(shí)保存在程序運(yùn)行的堆棧的某個(gè)不確定位置,不能取地址;②實(shí)參取地址用的操作符是是,而形參聲明變量類型為指針,需要地址值用的才是*;③聲明形參為指針的參數(shù)的實(shí)參只能為地址值。
故先把修改后的代碼列出,修改要點(diǎn)是把“*NewPerson1().Speak()”改為“var b=NewPerson1();(b).Speak()”,同時(shí)把“NewPerson2().Speak()”改成“var a=NewPerson2();(a).Speak()”,代碼列出如下:
package main;
import "fmt";
type PersonA struct{
name string
}
func (p *PersonA) Speak () {
fmt.Println ( "person speak" ,p.name)
}
func (p PersonA) Walk ( ){
fmt . Println ( "person walk",p.name)}
func NewPerson1()(p PersonA){
return PersonA{"new Person1"}}
func NewPerson2()(p PersonA){
return PersonA{"new Person2"}}
func main () {
var a=NewPerson2 (); (a).Speak ();?
a .Walk ();
fmt. Println ("--------------------")?;
var b=NewPerson1 ();(b).Speak ();
b.Walk ()}
go代碼調(diào)試效果
關(guān)于指針變量的使用這一點(diǎn)go語(yǔ)言和其他有指針的程序語(yǔ)言如c語(yǔ)言是一樣的,從來(lái)只有返回值為地址/指針,而從沒(méi)有在賦值前給返回值取地址這種運(yùn)算,類似的錯(cuò)誤晚點(diǎn)再整理。
不一樣的是,go語(yǔ)言更簡(jiǎn)單go語(yǔ)言函數(shù)可以使用結(jié)構(gòu)體或者結(jié)構(gòu)體的指針(pointer)以傳遞結(jié)構(gòu)體參數(shù),而且和c語(yǔ)言不一樣的是,go語(yǔ)言沒(méi)有區(qū)分結(jié)構(gòu)體指針和結(jié)構(gòu)體訪問(wèn)成員的運(yùn)算符,go語(yǔ)言只有“.”適用于兩種情況,而沒(méi)有c語(yǔ)言為結(jié)構(gòu)體指針專門準(zhǔn)備的“-”運(yùn)算符。
可以使用結(jié)構(gòu)體指針,作為結(jié)構(gòu)體的方法的參數(shù)以指代自身嗎,
【golang】?jī)?nèi)存逃逸常見(jiàn)情況和避免方式
因?yàn)槿绻兞康膬?nèi)存發(fā)生逃逸,它的生命周期就是不可知的,其會(huì)被分配到堆上,而堆上分配內(nèi)存不能像棧一樣會(huì)自動(dòng)釋放,為了解放程序員雙手,專注于業(yè)務(wù)的實(shí)現(xiàn),go實(shí)現(xiàn)了gc垃圾回收機(jī)制,但gc會(huì)影響程序運(yùn)行性能,所以要盡量減少程序的gc操作。
1、在方法內(nèi)把局部變量指針?lè)祷?,被外部引用,其生命周期大于棧,則溢出。
2、發(fā)送指針或帶有指針的值到channel,因?yàn)榫幾g時(shí)候無(wú)法知道那個(gè)goroutine會(huì)在channel接受數(shù)據(jù),編譯器無(wú)法知道什么時(shí)候釋放。
3、在一個(gè)切片上存儲(chǔ)指針或帶指針的值。比如[]*string,導(dǎo)致切片內(nèi)容逃逸,其引用值一直在堆上。
4、因?yàn)榍衅腶ppend導(dǎo)致超出容量,切片重新分配地址,切片背后的存儲(chǔ)基于運(yùn)行時(shí)的數(shù)據(jù)進(jìn)行擴(kuò)充,就會(huì)在堆上分配。
5、在interface類型上調(diào)用方法,在Interface調(diào)用方法是動(dòng)態(tài)調(diào)度的,只有在運(yùn)行時(shí)才知道。
1、go語(yǔ)言的接口類型方法調(diào)用是動(dòng)態(tài),因此不能在編譯階段確定,所有類型結(jié)構(gòu)轉(zhuǎn)換成接口的過(guò)程會(huì)涉及到內(nèi)存逃逸發(fā)生,在頻次訪問(wèn)較高的函數(shù)盡量調(diào)用接口。
2、不要盲目使用變量指針作為參數(shù),雖然減少了復(fù)制,但變量逃逸的開(kāi)銷更大。
3、預(yù)先設(shè)定好slice長(zhǎng)度,避免頻繁超出容量,重新分配。
Go語(yǔ)言變量的作用域
2021-10-22
每一個(gè)變量(常量、類型或函數(shù))在程序中都有一定的作用范圍。稱之為作用域。
Go語(yǔ)言在編譯時(shí)會(huì)檢查每一個(gè)變量是否使用過(guò),未使用過(guò)的變量就會(huì)編譯錯(cuò)誤。
根據(jù)變量定義位置的不同,可以分為以下三個(gè)類型:
在函數(shù)體內(nèi)被聲明的變量稱之為局部變量,作用在函數(shù)體內(nèi),函數(shù)的參數(shù)和返回值變量都屬于局部變量。局部變量不會(huì)一直存在,在函數(shù)被調(diào)用時(shí)存在,函數(shù)調(diào)用結(jié)束后變量就會(huì)被銷毀,即生命周期。
例子:其中a、b均為局部變量,只會(huì)在main函數(shù)內(nèi)有效
在函數(shù)體外被聲明的變量稱之為全局變量,作用于所有源文件。不包含這個(gè)全局變量的源文件需要使用"import"關(guān)鍵字引入全局變量所在的源文件之后才能使用這個(gè)全局變量。
全局變量聲明必須以 var 關(guān)鍵字開(kāi)頭,如果想要在外部包中使用全局變量的首字母必須大寫。
例如:global為全局在main2和main函數(shù)中都能使用
函數(shù)名后面的小括號(hào)里定義的變量, 用于接受來(lái)自調(diào)用函數(shù)的參數(shù)。用于接收調(diào)用該函數(shù)時(shí)傳入的參數(shù)。
例如:下面的例子中,第十七行a、b為sum函數(shù)定義的形參,用于傳入main函數(shù)中的AF、BF
Go 如何查看一個(gè)變量的內(nèi)存地址 理解指針問(wèn)題
熟悉C語(yǔ)言的同學(xué)都知道,查看一個(gè)變量的地址在處理指針的相關(guān)問(wèn)題的時(shí)候直觀重要,在C中直接取地址符 即可。那么在Go語(yǔ)言中如何查看一個(gè)變量的地址,我們使用unsafe.Pointer() 函數(shù)來(lái)查看一個(gè)變量的內(nèi)存地址。
舉例:
type Vertex struct {
X, Y float64
}
func (v Vertex) sqrt() float64 {
return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
func (v Vertex) scale(f float64) { //帶 號(hào) 和不帶*號(hào)的區(qū)別 可以從內(nèi)存地址來(lái)看出
fmt.printf("=======", unsafe.Pointer(v))//v 本身就是指針 存儲(chǔ)的就是地址 不用取地址
v.X = x.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex{3, 4}
fmt.printf("=======", unsafe.Pointer(v))
v.scale(10)
fmt.Println(v.sqrt())
}
//帶 號(hào) 打印的結(jié)果 ====== -%!(EXTRA unsafe.Pointer=0xc00006e070)======%!(EXTRA unsafe.Pointer=0xc00006e070) 相同
//不帶 號(hào) 打印的結(jié)果 ======%!(EXTRA unsafe.Pointer=0xc000094060)======%!(EXTRA unsafe.Pointer=0xc000094090) 不同
去掉*號(hào) 在scale()方法中要對(duì) v 進(jìn)行取地址操作
go語(yǔ)言,為什么range循環(huán)取的指針地址和直接用數(shù)組取的指針地址不一樣,求指教
因?yàn)楸闅vmyviewlist時(shí),實(shí)際上是復(fù)制myviewlist數(shù)組/切片中的元素到局部變量vw中。局部變量vw的地址當(dāng)然和myviewlist[0]的地址不一樣。
名稱欄目:go語(yǔ)言返回局部變量地址 go語(yǔ)言全局變量
標(biāo)題來(lái)源:http://fisionsoft.com.cn/article/docpopi.html


咨詢
建站咨詢
