go語言的變量聲明并賦值運算符(:=)

go語言的變量聲明并賦值運算符(:=)

基本功能

聲明并且賦值一個變量,其好處是不需要寫var三個字母,另外不需要寫類型,go語言會自動根據(jù)賦值的內容確定類型(但是這一點我不覺得是優(yōu)點,因為就不知道變量的類型是什么了)。

格式:
var := value

使用限制
不能在函數(shù)外面使用,即不能用來聲明全局變量。

== 例子 1

$ cat main.c
package main

import "fmt"

func main() {
    a := 100
    fmt.Printf("&a=%p\n", &a);
}

$ go build && main
&a=0xc42000e260

聲明并賦值變量a

== 例子 2

$ cat main.c
package main

import "fmt"

func main() {
    var a int = 100
    fmt.Printf("&a=%p\n", &a);
    a := 100
    fmt.Printf("&a=%p\n", &a);
}

$ go build && main
# main
./main.go:8: no new variables on left side of :=

第8行聲明并賦值變量a失敗,因為變量a已經(jīng)在第6行聲明過了。

== 例子 3

$ cat main.c
package main

import "fmt"

var a int = 100

func main() {
    fmt.Printf("&a=%p\n", &a);
    a := 100 
    fmt.Printf("&a=%p\n", &a);
}

$ go build && main
&a=0x4f8018
&a=0xc42000e268

雖然在第5行有聲明了一個全局變量a,在第9行依然可以聲明并賦值變量a,此時的a和全部變量a不是一個變量,打出來的地址不相同。

== 例子 4

$ cat main.c
package main

import "fmt"

func main() {
    a := 100 
    fmt.Printf("&a=%p\n", &a);
    {
        a := 100 
        fmt.Printf("&a=%p\n", &a);
    }
}

$ go build && main
&a=0xc420058168
&a=0xc420058198

第6行聲明并賦值了一個函數(shù)變量a,在第9行聲明并賦值了一個塊變量a,他們是兩個不同的變量。

總結v:=value的用法

  1. go在當前名字域范圍內搜索變量v
    • 如果已經(jīng)找到v那么報錯:no new variables on left side of :=
    • 如果沒有找到,那么在當前名字域范圍內定義變量v
  2. go并不在當前名字域的外層來搜搜變量
    • 如果是直接的引用或者賦值除外,e.g., v=value, or w=v
  3. 當前名字域包括函數(shù)域,或者塊域

多變量的聲明賦值

== 例子1

$ cat main.c
package main

import "fmt"

func foo() (int, int) {
    return 100, 200
}

func main() {
    a, b := foo()
    fmt.Printf("&a=%p, &b=%p\n", &a, &b);
}

$ go build && main
&a=0xc420058168, &b=0xc420058190

同時聲明并賦值兩個變量。

== 例子 2

$ cat main.c
package main

import "fmt"

func foo() (int, int) {
    return 100, 200
}

func main() {
    var a int = 0;
    fmt.Printf("&a=%p\n", &a);
    a, b := foo()
    fmt.Printf("&a=%p, &b=%p\n", &a, &b);
}

$ go build && main
&a=0xc42000e260
&a=0xc42000e260, &b=0xc42000e280

第10行已經(jīng)聲明了變量a,第12行就不在重新定義變量a,只定義了變量b;可以看到兩個a打印出來的是同一個。

== 例子 3

$ cat main.c
package main

import "fmt"

func foo() (int, int) {
    return 100, 200
}

func main() {
    var a int = 0;
    var b int = 0;
    fmt.Printf("&a=%p\n", &a);
    a, b := foo()
    fmt.Printf("&a=%p, &b=%p\n", &a, &b);
}

$ go build && main
# simple
./main.go:13: no new variables on left side of :=

第13行聲明的變量a和b在前面均已經(jīng)聲明過,沒有新的變量。

總結多聲明賦值v1,v2,v3,:=value1,value2,value3,操作的用法

  1. 對多變量的賦值至少有一個是新變量。
    • 對新變量在當前名字域創(chuàng)建變量
    • 對老變量則使用已經(jīng)存在的老變量,注意老變量也必須是在當前名字域內的老變量,不含外層變量。
package main

import "fmt"

func foo() (int, int) {
    return 100, 200
}

var b int = 0;
func main() {
    var a int = 0;
    fmt.Printf("&a=%p, &b=%p\n", &a, &b);
    a, b := foo()
    fmt.Printf("&a=%p, &b=%p\n", &a, &b);
}

$ go build && main
&a=0xc42006a018, &b=0x516b98
&a=0xc42006a018, &b=0xc42006a048

第11行聲明了變量a,在第13行聲明變量a和b的時候,因為a在第11行已經(jīng)聲明過了,所以這里不再定義新的變量a,而變量b雖然在第9行聲明了全局變量,但是根據(jù)聲明并賦值運算符(:=)的規(guī)則,在此并不會檢測全局變量區(qū),而只在當前名字域(即函數(shù)main)范圍內查找b,結果是沒有定義,所以在此會定義一個新變量b,這個變量b和全局變量b不是同一個變量。

結論

  1. 聲明并賦值運算符(:=)左邊至少得有一個變量是沒有定義的。
  2. 左邊變量有沒有定義的標準是在當前名字域范圍內,即當前語句塊,或者當前函數(shù);而不管是否在外層名字域范圍內已經(jīng)定義。
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容