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

歡迎訪問 生活随笔!

生活随笔

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

生活经验

Go 学习笔记(6)— 变量定义、变量声明、变量作用域

發(fā)布時間:2023/11/27 生活经验 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go 学习笔记(6)— 变量定义、变量声明、变量作用域 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 變量定義

Go 語言變量名由字母、數字、下劃線組成,其中首個字符不能為數字。聲明變量的一般形式是使用 var 關鍵字:

var varName dataType [= value]

Go 語言和許多編程語言不同,它在聲明變量時將變量的類型放在變量的名稱之后。

這樣做的好處就是可以避免像 C 語言中那樣含糊不清的聲明形式,例如:

// C 語言寫法
int* a, b, c; 
// 創(chuàng)建一個 int 型指針 a 和兩個 int 型變量 b,c

而在 Go 中,則可以輕松地將它們都聲明為指針類型。

2. 變量聲明

當一個變量被聲明之后,系統(tǒng)自動賦予它該類型的零值: int 為 0, float 為 0.0, bool 為 false, string 為空字符串,指針為 nil 等。所有的內存在 Go 中都是經過初始化的。

在C語言中,變量在聲明時,并不會對變量對應內存區(qū)域進行清理操作。此時,變量值可能是完全不可預期的結果。開發(fā)者需要習慣在使用C語言進行聲明時要初始化操作,稍有不慎,就會造成不可預知的后果。

在網絡上只有程序員才能看懂的“燙燙燙”和“屯屯屯”的梗,就來源于 C/C++ 中變量默認不初始化。

微軟的 VC 編譯器會將未初始化的棧空間以 16 進制的 0xCC 填充,而未初始化的堆空間使用 0xCD 填充,而 0xCCCC 和 0xCDCD 在中文的 GB2312 編碼中剛好對應“燙”和“屯”字。

因此,如果一個字符串沒有結束符\0,直接輸出的內存數據轉換為字符串就剛好對應“燙燙燙”和“屯屯屯”。

變量的命名規(guī)則遵循駱駝命名法,即首個單詞小寫,每個新單詞的首字母大寫,例如: numShipsstartDate

2.1 單變量聲明

  1. 指定變量類型,聲明后若不賦值,則使用該類型的默認值;
var varName dataType = value
  1. 根據值由編譯器自行判定變量類型;
var varName = value
  1. 省略關鍵字 var , 注意 := 左側的變量不應該是已經聲明過的,否則會導致編譯錯誤,該種聲明只能使用于函數或者方法;
varName := value

例如:

var a int = 10var b = 10c := 10

使用示例:

package mainvar a = "臥虎藏龍"
var b string = "www.wohu.com"
var c boolfunc main() {d := 100println(a, b, c, d)
}

2.2 多變量聲明

  1. 指定變量類型,聲明后若不賦值,則使用默認值;
var name1 name2 name3 int = v1, v2, v3
  1. 根據值自行判定變量類型;
var name1, name2, name3 = v1, v2, v3
  1. 省略 var, 注意 := 左側的變量不應該是已經聲明過的,否則會導致編譯錯誤;
name1, name2, name3 := v1, v2, v3
  1. 全局變量

    這種因式分解關鍵字的寫法一般用于聲明全局變量
var (name1 typename2 type)

注意: 一般建議一行只寫一個變量,這樣方便代碼閱讀

Go 語言中,定義變量要么通過聲明、要么通過 makenew 函數,不一樣的是 makenew 函數屬于顯式聲明并初始化。

如果我們聲明的變量沒有顯式聲明初始化,那么該變量的默認值就是對應類型的零值。從下面的表格可以看到,可以稱為引用類型的零值都是 nil

類型零值
int、float0
boolfalse
string“” 空字符串
struct內部字段的零值
slicenil
mapnil
指針nil
函數nil
channil
interfacenil

3. 使用示例

package mainvar x, y int
var (a intb bool
)
var c, d int = 1, 2// "hello" 是字符串必須用雙引號 " " 包含,如果用單引號包含則會報錯,單引號只能包含單個字符 
// invalid character literal (more than one character)var e, f = 123, "hello"// 這種不帶聲明格式的只能在函數體中出現,而不可以用于全局變量的聲明與賦值
// g, h := 123, "hello"func main() {g, h := 123, "hello"println(x, y, a, b, c, d, e, f, g, h)
}

運行結果:

0 0 0 false 1 2 123 hello 123 hello

4. 注意事項

在相同的代碼塊中,我們不可以再次對于相同名稱的變量使用初始化聲明,如下代碼

package mainimport "fmt"func main() {var a int = 2fmt.Println("a is ", a)a := 5fmt.Println("a is ", a)
}

編譯器會報錯誤

# command-line-arguments
src/main.go:32:4: no new variables on left side of :=

但是 a = 20 是可以的,因為這是給相同的變量賦予一個新的值。

  1. 如果你在定義變量 a 之前使用它,則會得到編譯錯誤 undefined: a

  2. 如果聲明了一個局部變量卻沒有在相同的代碼塊中使用它,同樣會得到編譯錯誤 a declared and not used

  3. 空白標識符也被用于拋棄值,如值 5 在 _, b = 5, 7 中被拋棄。

_ 也叫作匿名變量,匿名變量不占用內存空間,不會分配內存。匿名變量與匿名變量之間也不會因為多次聲明而無法使用。 實際上是一個只寫變量,你不能得到它的值。這樣做是因為 Go 語言中你必須使用所有被聲明的變量,但有時你并不需要使用從一個函數得到的所有返回值。

注意:在多個短變量聲明和賦值中,至少有一個新聲明的變量出現在左值中,即便其他變量名可能是重復聲明的,編譯器也不會報錯,代碼如下,編譯器不會報 err 重復定義。

conn, err := net.Dial("tcp", "127.0.0.1:8080")
conn2, err := net.Dial("tcp", "127.0.0.1:8080")

5. 變量作用域

Go 語言中變量可以在三個地方聲明:

  1. 函數內定義的變量稱為局部變量

  2. 函數外定義的變量稱為全局變量

  3. 函數定義中的變量稱為形式參數

  • 全局作用域

在任何地方都可以訪問的變量,稱其具有全局作用域。在 Go 語言中,全局作用域有兩類:

  1. Go 語言內置的預聲明標識符(包括預聲明的類型名、關鍵字、內置函數等)它們具有全局作用域,在任意命名空間內都可見。

  2. Go 語言包內以大寫字母開頭的標識符( 包括變量、常量、函數和方法名、自定義類型、結構字段等),它們具有全局作用域,在任意命名空間內都可見。

  • 包內作用域

Go 語言包內定義的以小寫字母開頭的標識符(變量、常量、函數和方法名、自定義類型、結構字段等〉,它們在本包可見,在其他包都是不可見的,這些標識符具有包內作用域。

  • 隱式作用域

每個代碼塊內定義的變量稱為“局部變量”這些局部變量只在當前代碼塊內可見,其作用域屬于當前代碼塊的隱式作用域。

不要將作用域和生命周期混為一談。聲明語句的作用域對應的是一個源代碼的文本區(qū)域;它是一個編譯時的屬性。一個變量的生命周期是指程序運行時變量存在的有效時間段,在此時間區(qū)域內它可以被程序的其他部分引用;是一個運行時的概念。

句法塊是由花括弧所包含的一系列語句,就像函數體或循環(huán)體花括弧包裹的內容一樣。句法塊內部聲明的名字是無法被外部塊訪問的。這個塊決定了內部聲明的名字的作用域范圍。

我們可以把塊(block)的概念推廣到包括其他聲明的群組,這些聲明在代碼中并未顯式地使用花括號包裹起來,我們稱之為詞法塊。對全局的源代碼來說,存在一個整體的詞法塊,稱為全局詞法塊;對于每個包、每個 forifswitch 語句,也都有對應詞法塊;

每個 switchselect 的分支也有獨立的詞法塊;當然也包括顯式書寫的詞法塊(花括弧包含的語句)。

for 循環(huán)類似, ifswitch 語句也會在條件部分創(chuàng)建隱式詞法域,還有它們對應的執(zhí)行體詞法域。下面的 if-else 測試鏈演示了 x 和 y 的有效作用域范圍:

if x := f(); x == 0 {fmt.Println(x)
} else if y := g(x); x == y {fmt.Println(x, y)
} else {fmt.Println(x, y)
}
fmt.Println(x, y) // compile error: x and y are not visible here

第二個 if 語句嵌套在第一個內部,因此第一個 if 語句條件初始化詞法域聲明的變量在第二個 if 中也可以訪問。 switch 語句的每個分支也有類似的詞法域規(guī)則:條件部分為一個隱式詞法域,然后是每個分支的詞法域。

if f, err := os.Open(fname); err != nil { // compile error: unused: freturn err
}
f.ReadByte() // compile error: undefined f
f.Close()    // compile error: undefined f

變量 f 的作用域只在 if 語句內,因此后面的語句將無法引入它,這將導致編譯錯誤。你可能會收到一個局部變量 f 沒有聲明的錯誤提示,具體錯誤信息依賴編譯器的實現。

通常需要在 if 之前聲明變量,這樣可以確保后面的語句依然可以訪問變量:

f, err := os.Open(fname)
if err != nil {return err
}
f.ReadByte()
f.Close()

5.1 局部變量

在函數體內聲明的變量稱之為局部變量,它們的作用域只在函數體內,參數和返回值變量也是局部變量。

package mainimport "fmt"func main() {/* 聲明局部變量 */var a, b, c int /* 初始化參數 */a = 10b = 20c = a + bfmt.Printf ("結果: a = %d, b = %d and c = %d\n", a, b, c)
}

5.2 全局變量

在函數體外聲明的變量稱之為全局變量,全局變量聲明必須以 var 關鍵字開頭,如果想要在外部包中使用全局變量的首字母必須大寫。全局變量可以在整個包甚至外部包(被導出后)使用。

package mainimport "fmt"/* 聲明全局變量 */
var g intfunc main() {/* 聲明局部變量 */var a, b int/* 初始化參數 */a = 10b = 20g = a + bfmt.Printf("結果: a = %d, b = %d and g = %d\n", a, b, g)
}

Go 語言程序中全局變量與局部變量名稱可以相同,但是函數內的局部變量會被優(yōu)先考慮。

package mainimport "fmt"/* 聲明全局變量 */
var g int = 20func main() {/* 聲明局部變量 */var g int = 10fmt.Printf ("結果: g = %d\n",  g)
}

5.3 形式參數

package mainimport "fmt"/* 聲明全局變量 */
var a int = 20;func main() {/* main 函數中聲明局部變量 */var a int = 10var b int = 20var c int = 0fmt.Printf("main()函數中 a = %d\n",  a);c = sum( a, b);fmt.Printf("main()函數中 c = %d\n",  c);
}/* 函數定義-兩數相加 */
func sum(a, b int) int {fmt.Printf("sum() 函數中 a = %d\n",  a);fmt.Printf("sum() 函數中 b = %d\n",  b);return a + b;
}

以上實例執(zhí)行輸出結果為:

main()函數中 a = 10
sum() 函數中 a = 10
sum() 函數中 b = 20
main()函數中 c = 30

總結

以上是生活随笔為你收集整理的Go 学习笔记(6)— 变量定义、变量声明、变量作用域的全部內容,希望文章能夠幫你解決所遇到的問題。

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