Golang入門筆記-03-語言基本數據類型

2021-02-13 蒼茫誤此生

1. 常量1.1 常量的定義

常量是一種特殊的變量,被初始化之後就無法再改變。

Go 語言中,常量的類型只能是布爾型數字型(整型、浮點型和複數)字符串型

常量可以使用關鍵字 const 來定義,定義格式為 const variable [type] = value。

1const m string = "abc" // 顯示聲明
2const n = "xyz" // 隱式聲明

常量的值必須在編譯時能確定,給常量賦值時可以涉及表達式的計算,但計算值必須能在編譯時確定。

1const m = 2 / 3 // 正確
2const n = getValue() // 錯誤,編譯時自定義函數屬於未知,無法用於常量賦值,但可以使用內置函數,如 len()

1.2 枚舉

常量也可以用於枚舉:

Unknown 表示未知性別,Female 表示女性,Male 表示男性。

1const (
2 Unknown = 0
3 Female = 1
4 Male = 2
5)

itoa 是一個特殊的常量,itoa 在 const 關鍵字出現時被重置為 0;const  中每多聲明一行常量,itos 會自動加 1( itoa 可理解成常量的行索引)。如:

1const (
2 a = itoa // a 的值為 0
3 b = itoa // b 的值為 1
4 c = itoa // c 的值為 2
5)

當聲明多行常量時,若不指定常量的值和類型,那麼該常量的類型和值與上一個常量相同

1const (
2 a = 100
3 b // b 的值為 100
4)

1const (
2 a = itoa // a 的值為 0
3 b // b 的值為 1
4 c // c 的值為 2
5)

我們來看一個例子:

1package main
2
3import "fmt"
4
5func main() {
6 const (
7 a = iota // 0
8 b // 1
9 c // 2
10 d = "ha" // iota += 1
11 e // "ha" iota += 1
12 f = 100 // iota +=1
13 g // 100 iota += 1
14 h = iota // 7
15 i // 8
16 )
17
18 fmt.Println(a, b, c, d, e, f, g, h, i)
19}

運行結果為:

10 1 2 ha ha 100 100 7 8

2. 變量2.1 定義變量

我們在上一篇文章 Golang 入門筆記-02-Go 語言基本語法和結構 中已闡述了變量的定義方式和注意點。

2.2 值類型和引用類型

基本數據類型 int,float,bool,string 以及數組結構體都屬於值類型值類型的變量直接存儲值,內存通常在中分配。

指針,slice,map 和 chan 等都屬於引用類型引用類型的變量存儲的是地址,內存通常在中分配,比棧擁有更大的空間,通過 GC 進行回收。

Go 語言中可以通過 & 來獲取變量的內存地址,如獲取變量 i 的內存地址:&i。

若一個變量被引用,那麼當該變量發生變化時,該變量的引用都會指向被修改後的內容。

我們來看一個例子:

1package main
2
3import "fmt"
4
5func main() {
6 a := 1
7 c := &a // c 的類型為 *int,是變量 a 的引用
8 d := &a // d 的類型為 *int,是變量 a 的引用
9 fmt.Println("c = ", c, ", d = ", d)
10 fmt.Println("*c = ", *c, ", *d = ", *d)
11
12 a = 2 // 修改 a 的值,引用類型變量 c 與 d 會指向修改後的 a
13 fmt.Println("c = ", c, ", d = ", d)
14 fmt.Println("*c = ", *c, ", *d = ", *d)
15}

運行結果為:

1c = 0xc00000a0a0 , d = 0xc00000a0a0
2*c = 1 , *d = 1
3c = 0xc00000a0a0 , d = 0xc00000a0a0
4*c = 2 , *d = 2

3. 基本類型和運算符3.1 基本類型3.1.1 布爾類型

定義 bool 類型的變量:

1var b1 bool = true
2var b2 = true
3b3 := false

bool 類型的值只能是 true 或 false。

可以通過運算符等於 == 或不等於 != 得到 bool 類型的值,如:

1var m = 6
2
3m == 5 // false
4m == 6 // true
5m != 5 // true
6m != 6 // false

還可以通過與邏輯運算符非 !,與 && ,或 || 結合得到 bool 類型的值。

Go 語言中,&& 和 || 具有快捷性質,當 && 和 || 左邊的表達式已經能夠決定整個表達式結果時(當 && 左邊值為 false 或 || 左邊值為 true 時),右邊的表達式不會被執行。因此,我們應儘量將複雜的表達式放在右邊,以減少運算量。

1var T = true
2var F = false
3
4!T // false
5!F // true
6T && T // true
7T && F // false
8F && T // false
9F && F // false
10T || T // true
11T || F // true
12F || T // true
13F || F // false

3.1.2 字符串

Go 語言中字符串的字節使用 UTF-8 編碼表示 Unicode 文本,所以 Go 語言字符串是變寬字符序列,這和其他語言(Java,Python)完全不同,後者為定寬字符序列。Go 語言這樣做,就不需要對 UTF-8 字符集文本進行編碼和解碼,節省了內存和空間。

Go 語言支持以下兩種形式定義字符串:解釋字符串

解釋字符串用雙引號包裹起來,如:

1package main
2
3import "fmt"
4
5func main() {
6 var s = "abc\nefg"
7
8 fmt.Println("s: ", s)
9}

運行結果為:

1s: abc
2efg

同時,以下這些字符串將被轉義:

\n:換行符

\r:回車符

\t:tab 鍵

\u 或 \U:Unicode 字符

\\:反斜槓

非解釋字符串

非解釋字符串用反引號包裹起來,與解釋字符串不同,非解釋字符串會按照用戶的輸入形式保存起來,且 \n,\r 等字符串不會被轉義, 如:

1package main
2
3import "fmt"
4
5func main() {
6 var s = `
7 Hello World!\n
8 I am a gopher!
9 `
10 fmt.Println("s: ", s)
11}

運行結果為:

1s:
2 Hello World!\n
3 I am a gopher!

Go 語言中的字符串和 C/C++ 不一樣,不以 \0 表示結尾,而是以長度限定。

長度為 0 的字符串是空字符串 ""。

可以通過 len() 來獲取字符串的長度,如:

1s := "abc"
2length := len(s) // 3

可以通過數組下標獲取字符串中的字符,如:

1s := "abc"
2s1 := s[0] // 'a'
3s2 := s[len(s)-1] // 'c'

可以通過 + 進行字符串拼接 :

1s1 := "Hello "
2s2 := "World"
3s3 := s1 + s2
4
5s4 := "He" + "llo "
6s4 += "World" // 等同於 s4 = s4 + "World"
7
8s5 := "Hello " + // 多行拼接 + 必須放在上一行
9 "World"

用 + 來拼接字符串效率並不是太高,後續我們會講到使用字節緩衝 bytes.Buffer 來進行字符串拼接。

3.1.3 整型

Go 語言中比較常見的整型有 int,uint,uintptr,這三個類型的長度和計算機架構有關。

還有與計算機架構無關的整型,從命名上就可以看出:

整型

int8(-128 ~ 127)

int16(-32768 ~ 32767)

int32(-2,147,483,648 ~ 2,147,483,647)

int64(-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)

無符號整型

uint8(0 ~ 255)

uint16(0 ~ 65,535)

uint32(0 ~ 4,294,967,295)

uint64(0 ~ 18,446,744,073,709,551,615)

可以通過前綴 0 來表示八進位數:0666;通過前綴 0x 表示十六進位數:0xEF;通過 e 來表示 10 的冪次方:1e2:100,3.14e20:3.14 x (10^20)。

注意 :

int 和 int64 不是同類型,以下代碼是錯誤的:

1var a int = 1
2var b int64 = 2
3a = b // a 與 b 屬於不同類型變量,無法賦值

聲明整型變量時,若不指定類型,默認為 int :

1var a = 1 // int
2b := 1 // int

短變量聲明中可以通過指定類型來定義變量:

1b := uint64(2) // uint64

3.1.4 浮點型

Go 語言中沒有 float 類型,僅存在兩種浮點類型(遵循 IEEE-754 標準):

浮點型默認值為 0.0。

float32 精確到小數點後 7 位,float64 精確到小數點後 15 位。

對於精確度要求較高的運算,應使用 float64 類型。

3.1.5 複數

Go 語言中,複數有兩種類型:

complex64(32 位實數和虛數)

complex128(64 位實數和虛數)

我們可以通過 a + bi 的方式來定義複數,a 表示實部,b 表示虛部,如:

1var c complex64 = 1 + 2i

可以通過 real(c) 和 imag(c) 函數來獲取複數變量 c 的實部虛部

複數和其他數據類型一樣,支持 == 和 != 的比較,比較時需注意複數精確度。若對性能沒有太高要求,建議使用精確度更高的 complex128 。

3.2 運算符3.2.1 位運算

注意:位運算是對給定數所對應的二進位數進行運算。

二元運算符

按位與 &

當兩位都為 1 時,值才為 1,否則值為 0:

11 & 1 // 1
21 & 0 // 0
30 & 1 // 0
40 & 0 // 0

按位或 |

兩位中有一個為 1,值即為 1,否則,值為 0:

11 | 1 // 1
21 | 0 // 1
30 | 1 // 1
40 | 0 // 0

按位異或 ^

若兩位的值相同,值為 0,若不相同,值為 1:

11 ^ 1 // 0
21 ^ 0 // 1
30 ^ 1 // 1
40 ^ 0 // 0

按位置零 &^

p &^ q:當 q 為 0 時,則結果為 p;否則,結果為 0:

11 &^ 0 // 1
21 &^ 1 // 0

一元運算符

位左移 <<

用法:a << n,將 a 左移 n 位,右側部分用 0 填充。相當於 a 乘以 2 的 n 次方。

11 << 10 // 2^10 -> 1KB
21 << 20 // 2^20 -> 1MB
31 << 30 // 2^30 -> 1GB

位右移 >>

用法:a >> n,將 a 右移 n 位,左側部分用 0 填充。相當於 a 除以 2 的 n 次方。

18 >> 1 // 8/(2^1) -> 4
21024 >> 6 // 1024/(2^6) -> 16

3.2.2 邏輯運算符

邏輯非 !

! 運算符表示取反,當 T 為 true 時,!T 值為 false,反之則為 true。

邏輯與 &&

&& 運算符表示邏輯與,當 && 兩邊表達式都為 true 時,值才為 true,否則為 false。

邏輯或 ||

|| 運算符表示邏輯或,當 || 有一邊表達式為 true 時,值就為 true,僅當兩邊表達式都為 false,值才為  false。

3.2.3 算術運算符

+ 加法

1a := 1
2b := 2
3c := a + b // 3

- 減法

1a := 2
2b := 1
3c := a - b // 1

* 乘法

1a := 1
2b := 2
3c := a * b // 2

/ 除法

1a := 2
2b := 1
3c := a / b // 2

% 求餘

1a := 6
2b := 5
3c := a % b // 1

++ 自增

變量自增 1。

1a := 1
2a++ // 2,相當於 a = a + 1

-- 自減

變量自減 1。

1a := 2
2a-- // 1,相當於 a = a - 1

注意

Go 語言中,++ 和 -- 僅僅是語句,不能作為表達式,以下寫法是錯誤的:

1a := 1
2b := a++ // 錯誤,++ 不能作為表達式

運算符的優先級

1優先級 運算符
2 7 ^ !
3 6 * / % << >> & &^
4 5 + - | ^
5 4 == != < <= >= >
6 3 <-
7 2 &&
8 1 ||

4. 指針

Go 語言為我們提供了指針功能,但不能進行指針運算。Go 語言允許我們控制特定數據結構,分配數量和內存訪問,有利於構建強大的網絡應用。

指針在 Go 語言中被拆分為兩個概念:

4.1 指針地址和指針類型

一個指針變量可以指向任意一個值的地址,它所指向的值的內存地址在 32 位和 64 位計算機上分別佔用 4 個字節和 8 個字節。(佔用字節大小與值大小無關)

當一個指針被定義後,若沒有被分配變量,則它的默認值為 nil(相當于于 C 語言中的 null)。

每一個變量都有一個地址,Go 語言中可以通過取址符號 & 來獲取一個變量的內存地址:

1a := 1
2p := &a // &a 表示取 a 的地址

我們通過一個例子來了解地址:

1package main
2
3import "fmt"
4
5func main() {
6 a := 1 // 定義 int 型變量 a
7 s := "abc" // 定義 string 型變量 s
8
9 fmt.Printf("%p %p", &a, &s) // 列印 a 和 s 的內存地址
10}

運行結果為:

10xc00000a0a0 0xc00003c1f0

任意變量都有地址,指針變量保存的就是地址。

4.2 獲取指針指向的值

可以對指針使用 * 操作符來獲取指針指向的值,例如我們定義了指針變量 p,可以通過 *p 來獲取指針 p 指向的值:

1package main
2
3import "fmt"
4
5func main() {
6 a := 1 // 定義 int 型變量 a
7 p := &a // 定義指針變量 p,p 保存 a 的地址
8
9 fmt.Printf("p -> type %T\n", p) // p 的類型
10 fmt.Printf("p -> value %p\n", p) // p 的值
11 fmt.Printf("*p -> type %T\n", *p) // *p 的類型
12 fmt.Printf("*p -> value %v\n", *p) // *p 的值
13}

運行結果為:

1p -> type *int
2p -> value 0xc00000a0a0
3*p ->type int
4*p -> value 1

4.3 通過指針修改值

指針也可以修改值:

1package main
2
3import "fmt"
4
5func swap(a, b *int) {
6 t := *a // t 保存 a 指向的變量的值
7
8 *a = *b // 將 b 指向的變量的值賦值給 a 指向的變量
9
10 *b = t // 將 t 賦值給 b 指向的變量
11}
12
13func main() {
14 m, n := 1, 2
15
16 swap(&m, &n)
17
18 fmt.Println(m, n)
19}

運行結果為:

12 1

* 指針操作符作為右值時,如 t := *a ,表示取指針指向的變量的值;作為左值時,如 *b = t,表示指針指向的變量。

我們還可以通過 new 函數來創建指針變量,如:

1s := new(string)
2*s = "Hello World"

new() 函數可以創建一個對應類型的指針,創建時會分配內存,創建完成後指針指向默認值。

注意

相關焦點

  • Golang入門教程——基本操作篇
    我們理解了函數的定義之後,下面來看看golang當中支持的一些特性。變量簡寫在變量聲明的時候,我們如果定義兩個相同類型的變量是可以把它們進行縮寫的。比如我們定義兩個int類型的變量,分別叫做a和b。那麼可以簡寫成這樣:var a, b int同樣,在函數當中,如果傳入的參數類型相同,也一樣是可以簡寫的。我們可以把x和y兩個參數縮寫在一起,用逗號分開,共享變量類型。
  • Golang入門教程——map篇
    今天是golang專題的第7篇文章,我們來聊聊golang當中map的用法。map這個數據結構我們經常使用,存儲的是key-value的鍵值對。在C++/java當中叫做map,在Python中叫做dict。
  • Golang入門教程——面向對象篇
    今天是golang專題的第9篇文章,我們一起來看看golang當中的面向對象的部分。在現在高級語言當中,面向對象幾乎是不可或缺也是一門語言最重要的部分之一。golang作為一門剛剛誕生十年的新興語言自然是支持面向對象的,但是golang當中面向對象的概念和特性與我們之前熟悉的大部分語言都不盡相同。比如Java、Python等,相比之下, golang這個部分的設計非常得簡潔和優雅(仁者見仁),所以即使你之前沒有系統地了解過面向對象,也沒有關係,也一定能夠看懂。
  • Golang語言標準庫 sync 包的 Once 怎麼使用?
    02基本用法Once 的使用也非常簡單,Once 只有一個 Do 方法,接收一個無參數無返回值的函數類型的參數 f,不管調用多少次 Do 方法,參數 f 只在第一次調用 Do 方法時執行。代碼示例:通過閱讀示例代碼,可以發現代碼中定義了兩個函數類型的變量 func1 和 func2,分別作為參數傳遞給兩次調用的 Do 方法,執行代碼,結果只列印第一次調用 Do 方法傳入的 func1 參數的值。
  • [GO語言基礎] 一.為什麼我要學習Golang以及GO語言入門普及
    開發的一種靜態強類型、編譯並髮型語言。如:數據傳送指令、算術運算指令、位運算指令、程序流程控制指令、串操作指令、處理器控制指令。電腦程式發給計算機處理器的命令就是「指令(instruction)」。最低級的指令是一串0和1,表示一項實體作業操作要運行(如「Add」)。根據指令類型,某個具體的存儲領域被稱作「寄存器(register)」,裡面包含了可用於調出指令的數據或數據存儲位置。
  • 物聯網開發筆記——嵌入式開發之Linux系統中C語言數據類型
    嵌入式開發學習C語言打下基礎。本節介紹《Linux系統中C語言數據類型》。1 數據類型分類short、int、long、char、float、double 這六個關鍵字代表C 語言裡的六種基本數據類型。
  • Swift語言開發入門視頻教程:playground基本用法
    Swift語言開發入門視頻教程:playground基本用法 蘋果公司在今年的WWDC大會上發布了全新程式語言Swift,Swift語言的發布對於開發者們,尤其是iOS開發者們來說確實是蘋果開發者大會的一大亮點
  • Win10 開發入門:C# 程式語言基礎之數據類型與變量
    根據網友們的反饋,在接下來的兩周內,IT之家將對C#語言的基礎知識進行介紹(每天一個知識點),以便你能夠基本讀懂項目中的C#代碼。但需要說明的是,文章能夠容納的內容是極其有限的,只能提供一個學習的思路,無法涉及到C#語言的方方面面,特別是很多高級主題,你需要藉助其他參考書籍來學習和掌握。
  • Go語言(Golang)環境搭建詳解
    最近寫了很多Go語言的原創文章,其中Go語言實戰系列30篇,近15W字,還有最近更新的Go經典庫系列,不過通過大家的諮詢來看,還是想要一些入門的知識,這一篇文章寫於2017年初,這裡再更新一下,發給大家。
  • 【Golang】圖解channel之數據結構
    channel被設計用來實現goroutine間的通信,按照golang的設計思想:以通信的方式共享內存。
  • Golang 類型斷言 vs 類型轉換
    這是一篇譯文,原文出處:https://www.sohamkamani.com/golang/type-assertions-vs-type-conversions
  • C語言入門級教程:基礎數據類型與基本算法,學編程從此刻開始!
    今天帶大家了解一下學C語言必備的基本數據類型和基本算法,適合剛學C以及零基礎的小夥伴! 話不多說,我們一起來學習吧~ 數據類型 ● 基本類型 基本類型就是我們在使用C語言時最基礎的數據類型,包括整形(短整型,基本整型,長整型)、字符型、浮點型(單、雙精度)以及枚舉類型。
  • Golang 入門筆記 - Channel
    原文如下:Go 語言使用 goroutine 可以輕鬆地實現並發。大家應該都知道,goroutine 是通過 channel 實現相互通信的。channel 確保 goroutine 和主線程時間可以相互通信。在這篇文章中,將會與大家討論如何創建 channel 和實現數據共享。
  • 在線學習Go編程的頂級Golang教程
    在本課程中,您將:· 了解語言的基本語法和控制結構· 應用Go的並發模型來構建大規模並行系統· 掌握類型的用途,如果您來自動態類型的語言(例如Javascript或Ruby),這尤其重要· 通過使用包來組織代碼· 使用Go運行時來構建和編譯項目· 深入了解該語言中的關鍵設計決策· 了解何時使用基本語言功能
  • Golang語言情懷-第46期 Go 語言標準庫翻譯 compress/bzip2
    Index返回首頁type StructuralError string當bzip2數據的語法不合法時,會返回本類型錯誤。func (StructuralError) Errorfunc (s StructuralError) Error() stringfunc NewReaderfunc NewReader(r io.Reader) io.ReaderNewReader返回一個從r讀取bzip2壓縮數據並解壓縮後返回給調用者的io.Reader。
  • 嚴蔚敏數據結構C語言版課後習題答案及筆記
    向然學習資料網為同學們提供嚴蔚敏數據結構C語言版課後習題答案及筆記
  • Golang 語言標準庫 bytes 包怎麼使用?
    ,分別是 byte 的字節類類型,和 rune 的字符類類型。}閱讀源碼,我們發現 Buffer 結構中的欄位 buf 是 []byte 類型,用於存儲數據,欄位 off 是 int 類型,用於記錄讀寫位置。
  • Java基本數據類型
    false二、Java數據類型基本概念:數據類型在計算機語言裡面,是對內存位置的一個抽象表達方式,可以理解為針對內存的一種抽象的表達方式。接觸每種語言的時候,都會存在數據類型的認識,有複雜的、簡單的,各種數據類型都需要在學習初期去了解,Java是強類型語言,所以Java對於數據類型的規範會相對嚴格。數據類型是語言的抽象原子概念,可以說是語言中最基本的單元定義,在Java裡面,本質上講將數據類型分為兩種:基本類型和引用數據類型。
  • Golang語言之字符串操作
    如有紕漏,後續會在「Go 語言研究院」https://www.golanghub.cn 修正。如果文章對您有所幫助,還請關注公眾號給予支持。var str string = "100" /** * param:string * return:int,error */ num, _ := strconv.Atoi(str) fmt.Printf("%T\n", num) /* * param str,進位,類型
  • Go語言從入門到精通-09| 映射數據類型的應用
    雖然整個軟體還比較脆弱,但基本的功能已經有了,可以瀏覽基本的靜態頁面,並且可以包含圖片等內容。今天我們繼續完善這個程序,在完善的過程中我們不斷的引入新的Go語言的內容。今天主要學習如下幾方面的內容:學習Go語言中的map數據類型HTTP協議中關於內容類型的規定修改服務端程序代碼,可以根據請求擴展名生成內容類型