本文介紹了 Go 語言中的基本概念,包括變數、數據類型、數據類型轉換以及進位轉換。我們將詳細探討整數、浮點數、字元、布爾值和字元串等數據類型,以及如何在實際編程中高效地使用它們。 ...
前言
一個程式就是一個世界,不論是使用哪種高級程式語言編寫程式, 變數都是其程式的基本組成單位,
變數
在 go 中 變數是用於存儲數據的命名空間(記憶體位置),它可以表示一個值,這個值在程式執行過程中可能會發生改變。
+-------------+ +---------------------+
| 變數名: myVar|------>| 記憶體地址: 0x12345678|
+-------------+ +---------------------+
| 數據值: 42 |
+---------------------+
關鍵概念
-
標識符(名稱): 變數具有一個唯一的名稱,用於在程式中引用它。變數名應遵循編程語言的命名規則,通常以字母、數字和下劃線組成,並且不能以數字開頭。關鍵字和預定義標識符可以查看附錄 :附錄
-
數據類型: 變數有一個與之關聯的數據類型,如整數、浮點數、布爾值或自定義類型。數據類型決定了變數可以存儲的值的範圍和類型。
-
值: 變數表示一個值,這個值可以在程式執行過程中改變。通過賦值操作,我們可以將一個新值存儲到變數中。
-
作用域: 變數在程式中的可見範圍稱為作用域。作用域決定了在哪些部分的代碼中可以訪問和修改變數。通常,局部變數在函數或代碼塊內部定義,全局變數在整個程式範圍內定義。
-
生命周期: 變數的生命周期是從創建到銷毀的過程。局部變數的生命周期通常與函數或代碼塊的執行周期相同;全局變數的生命周期從程式啟動到程式結束。
變數的使用
- go 中 局部變數的聲明方式有 4種
- go 中 全局變數的聲明方式有 2 種
示例
package main
import "fmt"
// 全局變數
var globalInt = 100
var globalFloat = 9.7
// 一次性聲明多個全局變數
var (
globalInt2 = 500
globalString2 = "netty"
)
func main() {
// 局部變數
// 1. 變數聲明
var age int
// 2. 變數賦值
age = 18
// 3. 變數使用
fmt.Println("age =", age)
// 2、聲明和賦值可以合併成一句
var age2 int = 19
fmt.Println("age2 =", age2)
// 以下代碼將會報錯,因為變數 age 重覆聲明
// var age int = 20
// fmt.Println("age =", age)
// 以下代碼將會報錯,因為浮點數不能直接賦值給整數類型變數
// var num int = 12.56
// fmt.Println("num =", num)
// 指定變數類型,使用預設值
var age3 int
fmt.Println(age2)
// 3、自動類型推斷
var name = "tom"
fmt.Println(name)
//4、 省略 var 關鍵字,使用 :=
gender := "男"
fmt.Println(gender)
// 一次性聲明多個局部變數
var n1, n2, n3 int
fmt.Println(n1)
fmt.Println(n2)
fmt.Println(n3)
// 一次性聲明多個局部變數並賦值
var n4, name2, n5 = 10, "jack", 7.8
fmt.Println(n4)
fmt.Println(name2)
fmt.Println(n5)
// 使用 := 一次性聲明多個局部變數並賦值
n6, height := 6.9, 100.6
fmt.Println(n6)
fmt.Println(height)
// 輸出全局變數
fmt.Println(globalInt)
fmt.Println(globalFloat)
fmt.Println(globalInt2)
fmt.Println(globalString2)
}
數據類型
Golang
變數的數據類型主要分為兩種:
- 基本數據類型
- 派生(複雜)數據類型:
類別 | 數據類型 | 說明 |
---|---|---|
基本數據類型 | bool | 布爾類型,值為 true 或 false |
int8, int16, int32, int64 | 有符號整數類型,分別占用 8, 16, 32, 64 位存儲空間 | |
uint8, uint16, uint32, uint64 | 無符號整數類型,分別占用 8, 16, 32, 64 位存儲空間 | |
int | 有符號整數類型,大小與操作系統位數相關(32 位或 64 位) | |
uint | 無符號整數類型,大小與操作系統位數相關(32 位或 64 位) | |
uintptr | 無符號整數類型,足以存儲指針的大小 | |
float32, float64 | 浮點數類型,分別占用 32 位和 64 位存儲空間 | |
complex64, complex128 | 複數類型,分別占用 64 位和 128 位存儲空間 | |
byte | 位元組類型,等同於 uint8 | |
rune | Unicode 字元類型,等同於 int32 | |
string | 字元串類型 | |
派生數據類型 | array | 固定長度的數組類型 |
slice | 可變長度的數組類型(切片) | |
map | 無序鍵值對集合(字典) | |
struct | 自定義數據結構(結構體) | |
interface | 定義一組方法的集合(介面) | |
pointer | 存儲變數記憶體地址的類型(指針) | |
channel | 用於協程間通信的類型(通道) | |
function | 函數類型 |
整數類型
簡單的說,就是用於存放整數值的,比如10,-45,6712等等。
有符號整數類型:
類型 | 是否有符號 | 占用空間 | 取值範圍 |
---|---|---|---|
int8 | 是 | 8 位 (1 位元組) | -128 到 127 (-2^7 到 2^7-1) |
int16 | 是 | 16 位 (2 位元組) | -32,768 到 32,767 (-2^15 到 2^15-1) |
int32 | 是 | 32 位 (4 位元組) | -2,147,483,648 到 2,147,483,647 (-2^31 到 2^31-1) |
int64 | 是 | 64 位 (8 位元組) | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 (-2^63 到 2^63-1) |
PS:127怎麼算出來的?
01111111 –>二進位 —》轉為十進位:
1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
= 64 + 32 + 16 + 8 + 4 + 2 + 1
= 127
PS:-128怎麼算出來的?
10000000 —>二進位 —>一看就是個負數
10000000 –》負數的二進位
減1:01111111
取反:10000000 —》得到一個正數 2^7 = 128
加負號:-128
無符號整數類型:
這些類型可用於表示不同範圍的非負整數值。
類型 | 是否有符號 | 占用空間 | 取值範圍 |
---|---|---|---|
uint8 | 否 | 8 位 (1 位元組) | 0 到 255 (0 到 2^8-1) |
uint16 | 否 | 16 位 (2 位元組) | 0 到 65,535 (0 到 2^16-1) |
uint32 | 否 | 32 位 (4 位元組) | 0 到 4,294,967,295 (0 到 2^32-1) |
uint64 | 否 | 64 位 (8 位元組) | 0 到 18,446,744,073,709,551,615 (0 到 2^64-1) |
表數範圍的邊界計算:
11111111= 2^7+127 = 128 + 127 = 255
00000000 = 0
其他整數類型
以下是一個完整的表格,將取值範圍放在同一個單元格中:
類型 | 是否有符號 | 占用空間 | 取值範圍 | 說明 |
---|---|---|---|---|
int | 是 | 32 位或64 位 (依賴操作系統) | 32 位: -2^31 到 2^31-1 64 位: -2^63 到 2^63-1 |
有符號整數,大小與操作系統位數相關 |
uint | 否 | 32 位或64 位 (依賴操作系統) | 32 位: 0 到 2^32-1 64 位: 0 到 2^64-1 |
無符號整數,大小與操作系統位數相關 |
uintptr | 否 | 32 位或64 位 (依賴操作系統) | 32 位: 0 到 2^32-1 64 位: 0 到 2^64-1 |
無符號整數,足以存儲指針的大小 |
byte | 否 | 8 位 (1 位元組) | 0 到 2^8-1 | 位元組類型,等同於 uint8 |
rune | 是 | 32 位 (4 位元組) | -2^31 到 2^31-1 | Unicode 字元類型,等同於 int32 |
這些類型在特定場景下(如操作系統相關編程、處理位元組和 Unicode 字元)非常有用。
PS:Golang的整數類型,預設聲明為int類型
查詢變數占用的位元組數
在 Go 語言中,可以使用 unsafe.Sizeof()
函數來查看變數占用的位元組數。unsafe.Sizeof()
函數返回一個變數所占用的位元組數,以 uintptr
類型表示。請註意,使用 unsafe
包可能會帶來潛在的安全風險和跨平臺相容性問題,因此在使用時要謹慎。
package main
import (
"fmt"
"unsafe"
)
func main() {
var a int32 = 10
var b float64 = 20.5
var c bool = true
var d byte = 255
var e rune = 'A'
var f string = "hello"
fmt.Printf("Size of int32: %d bytes\\n", unsafe.Sizeof(a))
fmt.Printf("Size of float64: %d bytes\\n", unsafe.Sizeof(b))
fmt.Printf("Size of bool: %d bytes\\n", unsafe.Sizeof(c))
fmt.Printf("Size of byte: %d bytes\\n", unsafe.Sizeof(d))
fmt.Printf("Size of rune: %d bytes\\n", unsafe.Sizeof(e))
fmt.Printf("Size of string: %d bytes\\n", unsafe.Sizeof(f))
}
在這個示例中,我們使用 unsafe.Sizeof()
函數查看了不同類型變數占用的位元組數,並將結果列印到控制台。請註意,對於 string
類型,unsafe.Sizeof()
函數返回的值是字元串頭部的大小,而不是實際字元串內容的大小。要獲取字元串內容的長度,可以使用 len()
函數。
這麼多整數類型,使用的時候該如何選擇呢?
Golang程式中整型變數在使用時,遵守保小不保大的原則,
即:在保證程式正確運行下,儘量使用占用空間小的數據類型
浮點類型
簡單的說,就是用於存放小數值的,比如3.14、0.28、-7.19等等。
浮點類型種類:
類型 | 是否有符號 | 占用空間 | 取值範圍及精度 | 說明 |
---|---|---|---|---|
float32 | 是 | 32 位 (4 位元組) | 1.18e-38 到 3.4e38(約 7 位有效數字) | 單精度浮點數 |
float64 | 是 | 64 位 (8 位元組) | 2.23e-308 到 1.8e308(約 16 位有效數字) | 雙精度浮點數(通常使用) |
在大多數情況下,推薦使用 float64
類型,因為它具有更高的精度和更廣泛的取值範圍。
PS:底層存儲空間和操作系統無關
PS:浮點類型底層存儲:符號位+指數位+尾數位,所以尾數位只是存了 一個大概,很可能會出現精度的損失。
浮點類型示例:
package main
import "fmt"
func main() {
// 定義正的 float32 類型變數
var num1 float32 = 3.14
fmt.Println(num1)
// 定義負的 float32 類型變數
var num2 float32 = -3.14
fmt.Println(num2)
// 使用科學計數法表示的 float32 類型變數
var num3 float32 = 314e-2
fmt.Println(num3)
// 使用科學計數法表示的 float32 類型變數
var num4 float32 = 314e+2
fmt.Println(num4)
// 使用科學計數法表示的 float32 類型變數
var num5 float32 = 314e+2
fmt.Println(num5)
// 使用科學計數法表示的 float64 類型變數
var num6 float64 = 314e+2
fmt.Println(num6)
// float32 類型變數可能存在精度損失
var num7 float32 = 256.000000916
fmt.Println(num7)
// float64 類型變數具有更高的精度
var num8 float64 = 256.000000916
fmt.Println(num8)
// Go 語言中預設的浮點類型為 float64
var num9 = 3.17
fmt.Printf("num9對應的預設的類型為:%T", num9)
}
字元類型
- Golang中沒有專門的字元類型,如果要存儲單個字元(字母),一般使用byte來保存。
- Golang中字元使用UTF-8編碼
- 查詢字元對應的UTF-8編碼表:http://www.mytju.com/classcode/tools/encode_utf8.asp
- ASCII碼表:
字元類型示例:
package main
import "fmt"
func main() {
// 定義 ASCII 字元類型的數據 (byte 類型)
var char1 byte = 'a'
fmt.Println(char1) // 輸出: 97
var char2 byte = '6'
fmt.Println(char2) // 輸出: 54
var char3 byte = '('
fmt.Println(char3 + 20) // 輸出: 40
// 字元類型本質上是一個整數,可以直接參与運算。輸出時,會將對應的碼值輸出。
// 字母、數字、標點等字元在底層按照 ASCII 進行存儲。
// 定義 Unicode 字元類型的數據 (int 類型)
var char4 int = '中'
fmt.Println(char4) // 輸出: 20013
// 漢字字元在底層對應的是 Unicode 碼值。
// 碼值為 20013,超出 byte 類型能存儲的範圍,因此使用 int 類型存儲。
// 總結:Go 語言的字元使用 UTF-8 編碼(Unicode 是對應的字元集,UTF-8 是 Unicode 的其中一種編碼方案)。
var char5 byte = 'A'
// 若要顯示對應的字元,必須採用格式化輸出
fmt.Printf("char5 對應的具體的字元為:%c", char5) // 輸出: A
}
布爾類型
- 布爾類型也叫bool類型,bool類型數據只允許取值true和false
- 布爾類型占1個位元組。
- 布爾類型適於邏輯運算,一般用於程式流程式控制制
package main
import "fmt"
func main() {
// 測試布爾類型的數值
var flag1 bool = true
fmt.Println(flag1) // 輸出: true
var flag2 bool = false
fmt.Println(flag2) // 輸出: false
var flag3 bool = 5 < 9
fmt.Println(flag3) // 輸出: true
}
字元串類型
字元串就是一串固定長度的字元連接起來的字元序列。
字元串示例
package main
import "fmt"
func main() {
// 1. 定義一個字元串
var s1 string = "全面擁抱Golang"
fmt.Println(s1)
// 2. 字元串是不可變的:指的是字元串一旦定義好,其中的字元的值不能改變
var s2 string = "abc"
// s2 = "def"
// s2[0] = 't'
fmt.Println(s2)
// 3. 字元串的表示形式
// (1) 如果字元串中沒有特殊字元,字元串的表示形式用雙引號
// var s3 string = "asdfasdfasdf"
// (2) 如果字元串中有特殊字元,字元串的表示形式用反引號 ``
var s4 string = `
package main
import "fmt"
func main(){
//測試布爾類型的數值:
var flag01 bool = true
fmt.Println(flag01)
var flag02 bool = false
fmt.Println(flag02)
var flag03 bool = 5 < 9
fmt.Println(flag03)
}`
fmt.Println(s4)
// 4. 字元串的拼接效果
var s5 string = "abc" + "def"
s5 += "hijk"
fmt.Println(s5)
// 當一個字元串過長的時候:註意:+ 保留在上一行的最後
var s6 string = "abc" + "def" + "abc" + "def" + "abc" + "def" +
"abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" +
"abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def" +
"abc" + "def" + "abc" + "def" + "abc" + "def" + "abc" + "def"
fmt.Println(s6)
}
基本數據類型的預設值
在Golang中數據類型都有一個預設值,當程式員沒有賦值時,就會保留預設值(預設值又叫零值)。
以下是一個表格,展示了 Go 語言中各種數據類型的預設值:
數據類型 | 預設值 | 說明 |
---|---|---|
int | 0 | 整數類型預設值 |
uint | 0 | 無符號整數類型預設值 |
float32 | 0.0 | 單精度浮點數預設值 |
float64 | 0.0 | 雙精度浮點數預設值 |
bool | false | 布爾類型預設值 |
string | "" | 空字元串預設值 |
array | 元素的預設值 | 數組元素類型的預設值 |
slice | nil | 切片類型預設值 |
map | nil | 映射類型預設值 |
pointer | nil | 指針類型預設值 |
function | nil | 函數類型預設值 |
channel | nil | 通道類型預設值 |
struct | 結構體欄位的預設值 | 結構體中各欄位類型的預設值 |
這個表格包含了 Go 語言中各種數據類型的預設值。當聲明一個變數而不指定初始值時,變數會被賦予其數據類型的預設值。例如,整數類型的預設值是 0,布爾類型的預設值是 false,字元串類型的預設值是空字元串("")。對於複合數據類型(如數組、切片、映射、結構體等),它們的預設值取決於其元素或欄位的數據類型。
基本數據類型之間的轉換
Go在不同類型的變數之間賦值時需要顯式轉換,並且只有顯式轉換(強制轉換)。
語法:
表達式T(v)將值v轉換為類型T
- T : 就是數據類型
- v : 就是需要轉換的變數
類型轉換示例
package main
import "fmt"
func main() {
// 類型轉換示例
// 聲明一個 int 類型變數
var num1 int = 100
fmt.Println(num1)
// 將 int 類型轉換為 float32 類型
var num2 float32 = float32(num1)
fmt.Println(num2)
// 註意:num1 的類型仍然是 int,只是將 num1 的值 100 轉換為了 float32 類型
fmt.Printf("%T\n", num1) // 輸出: int
// 將 int64 類型轉換為 int8 類型時,可能會發生數據溢出
var num3 int64 = 888888
var num4 int8 = int8(num3)
fmt.Println(num4) // 輸出: 56
// 將 int32 類型轉換為 int64 類型,併進行數值運算
var num5 int32 = 12
var num6 int64 = int64(num5) + 30
fmt.Println(num5)
fmt.Println(num6)
// 將 int64 類型轉換為 int8 類型時,可能會發生數據溢出
var num7 int64 = 12
var num8 int8 = int8(num7) + 127
// 編譯通過,但結果可能會溢出
fmt.Println(num8) // 輸出: -117
// 將 int64 類型轉換為 int8 類型時,可能會發生數據溢出
// var num9 int8 = int8(num7) + 128 // 編譯不會通過,因為 128 超出了 int8 的取值範圍
}
基本數據類型轉為string
在程式開發中,我們經常需要將基本數據類型轉成string類型。或者將string類型轉成基本數據類型。
方式1:mt.Sprintf(“%參數”,表達式) 推薦方式
package main
import (
"fmt"
)
func main() {
// 將 int 類型轉換為 string 類型
num1 := 42
str1 := fmt.Sprintf("%d", num1)
fmt.Printf("str1: %s, type: %T\n", str1, str1)
// 將 float64 類型轉換為 string 類型
num2 := 3.14159
str2 := fmt.Sprintf("%.2f", num2)
fmt.Printf("str2: %s, type: %T\n", str2, str2)
// 將 bool 類型轉換為 string 類型
flag := true
str3 := fmt.Sprintf("%t", flag)
fmt.Printf("str3: %s, type: %T\n", str3, str3)
}
按使用頻率排序的 fmt.Printf()
占位符:
占位符 | 說明 | 示例 |
---|---|---|
%v | 預設格式輸出,根據變數的類型自動選擇輸出格式 | fmt.Printf("%v", x) |
%s | 輸出字元串 | fmt.Printf("%s", x) |
%d | 輸出十進位整數 | fmt.Printf("%d", x) |
%f | 輸出浮點數,不使用科學計數法 | fmt.Printf("%f", x) |
%T | 輸出變數的類型 | fmt.Printf("%T", x) |
%t | 輸出布爾值 | fmt.Printf("%t", x) |
%x | 輸出十六進位整數,使用小寫字母 | fmt.Printf("%x", x) |
%X | 輸出十六進位整數,使用大寫字母 | fmt.Printf("%X", x) |
%b | 輸出整數的二進位表示 | fmt.Printf("%b", x) |
%e | 輸出科學計數法表示的浮點數,使用小寫字母 e |
fmt.Printf("%e", x) |
%E | 輸出科學計數法表示的浮點數,使用大寫字母 E |
fmt.Printf("%E", x) |
%g | 輸出浮點數,根據數值大小自動選擇使用 %f 或 %e 格式 | fmt.Printf("%g", x) |
%G | 輸出浮點數,根據數值大小自動選擇使用 %f 或 %E 格式 | fmt.Printf("%G", x) |
%p | 輸出指針的十六進位表示 | fmt.Printf("%p", x) |
%c | 輸出整數對應的 Unicode 字元 | fmt.Printf("%c", x) |
%o | 輸出八進位整數 | fmt.Printf("%o", x) |
%q | 輸出帶引號的字元串或字元,對於字元串,輸出雙引號;對於字元,輸出單引號 | fmt.Printf("%q", x) |
%U | 輸出 Unicode 碼點表示的字元串 | fmt.Printf("%U", x) |
%+v | 輸出結構體時,包含欄位名 | fmt.Printf("%+v", x) |
%#v | 輸出 Go 語言語法格式的值 | fmt.Printf("%#v", x) |
%% | 輸出一個百分號(% ) |
fmt.Printf("%%") |
%n | 輸出已寫入的位元組數(n 為 int 類型的指針) | fmt.Printf("%n", &x) |
方式2:使用strconv包的函數
package main
import (
"fmt"
"strconv"
)
func main() {
// 將 int 類型轉換為 string 類型
num1 := 42
str1 := strconv.Itoa(num1)
fmt.Printf("str1: %s, type: %T\n", str1, str1)
// 將 float64 類型轉換為 string 類型
num2 := 3.14159
str2 := strconv.FormatFloat(num2, 'f', 2, 64)
fmt.Printf("str2: %s, type: %T\n", str2, str2)
// 將 bool 類型轉換為 string 類型
flag := true
str3 := strconv.FormatBool(flag)
fmt.Printf("str3: %s, type: %T\n", str3, str3)
// 將 int64 類型轉換為 string 類型
num3 := int64(123456789)
str4 := strconv.FormatInt(num3, 10)
fmt.Printf("str4: %s, type: %T\n", str4, str4)
// 將 uint64 類型轉換為 string 類型
num4 := uint64(987654321)
str5 := strconv.FormatUint(num4, 10)
fmt.Printf("str5: %s, type: %T\n", str5, str5)
}
兩者差異
fmt.Sprintf()
和 strconv
包中的函數之間的主要區別在於性能和靈活性:
- 性能:
strconv
包中的函數通常比fmt.Sprintf()
更快,因為它們專門針對特定的數據類型進行了優化。fmt.Sprintf()
是一個通用的格式化字元串函數,因此它需要處理更多的類型和格式選項,這可能會導致性能略低於strconv
包中的函數。 - 靈活性:
fmt.Sprintf()
提供了更多的格式選項和控制,可以輕鬆地處理多種數據類型和格式。而strconv
包中的函數是專門針對特定數據類型的,因此在某些情況下可能不如fmt.Sprintf()
靈活。
根據實際需求和性能要求,可以選擇使用 fmt.Sprintf()
或 strconv
包中的函數進行數據類型轉換。在對性能要求不高的情況下,使用 fmt.Sprintf()
可能更方便和簡單。在對性能要求較高的情況下,可以考慮使用 strconv
包中的函數。
string轉為基本數據類型
package main
import (
"fmt"
"strconv"
)
func main() {
// 將 string 類型轉換為 int 類型
str1 := "42"
num1, err1 := strconv.Atoi(str1)
if err1 != nil {
fmt.Println("Error:", err1)
} else {
fmt.Printf("num1: %d, type: %T\n", num1, num1)
}
// 將 string 類型轉換為 float64 類型
str2 := "3.14159"
num2, err2 := strconv.ParseFloat(str2, 64)
if err2 != nil {
fmt.Println("Error:", err2)
} else {
fmt.Printf("num2: %f, type: %T\n", num2, num2)
}
// 將 string 類型轉換為 bool 類型
str3 := "true"
flag, err3 := strconv.ParseBool(str3)
if err3 != nil {
fmt.Println("Error:", err3)
} else {
fmt.Printf("flag: %t, type: %T\n", flag, flag)
}
// 將 string 類型轉換為 int64 類型
str4 := "123456789"
num3, err4 := strconv.ParseInt(str4, 10, 64)
if err4 != nil {
fmt.Println("Error:", err4)
} else {
fmt.Printf("num3: %d, type: %T\n", num3, num3)
}
// 將 string 類型轉換為 uint64 類型
str5 := "987654321"
num4, err5 := strconv.ParseUint(str5, 10, 64)
if err5 != nil {
fmt.Println("Error:", err5)
} else {
fmt.Printf("num4: %d, type: %T\n", num4, num4)
}
}
指針
&
取記憶體地址*
根據地址取值
package main
import "fmt"
func main() {
// 聲明一個整數變數 num
num := 42
fmt.Println("num:", num)
// 聲明一個指針變數 ptr
var ptr *int
// 將 num 的地址賦值給 ptr
ptr = &num
fmt.Println("ptr points to:", *ptr)
// 通過 ptr 訪問 num 的值
fmt.Println("Value of num through ptr:", *ptr)
// 通過 ptr 修改 num 的值
*ptr = 100
fmt.Println("New value of num:", num)
}
sequenceDiagram
participant main
participant num
participant ptr
main->>num: 聲明整數變數 num
Note over main,num: int num = 42
main->>ptr: 聲明指針變數 ptr
Note over main,ptr: int *ptr
main->>ptr: 將 num 的地址賦值給 ptr
Note over main,ptr: ptr = &num
main->>ptr: 通過 ptr 訪問 num 的值
Note over main,ptr: *ptr
main->>ptr: 通過 ptr 修改 num 的值
Note over main,ptr: *ptr = 100
指針細節
- 指針變數的地址不可以不匹配:不能指向不同數據類型
- 基本數據類型(又叫值類型),都有對應的指針類型,形式為*數據類型,比如int的對應的指針就是
*int
, float32對應的指針類型就是*float32
。依次類推。
附錄
關鍵字和預定義標識符
關鍵字是 Go 語言中具有特殊含義的單詞,用於控制語言結構。預定義標識符是 Go 語言中預先聲明的常量、類型、函數等。在命名變數、函數或類型時,應避免使用這些關鍵字和預定義標識符。
關鍵字就是程式發明者規定的有特殊含義的單詞,又叫保留字。
關鍵字:
go語言中一共有25個關鍵字。
關鍵字 | 說明 |
---|---|
break | 跳出迴圈或 switch 語句 |
default | switch 語句的預設分支 |
func | 聲明函數或方法 |
interface | 聲明介面類型 |
select | 用於從多個通道中接收數據 |
case | switch 語句的每個分支 |
defer | 延遲執行函數,直到包含該 defer 語句的函數執行完畢 |
go | 以併發方式運行函數 |
map | 聲明映射類型 |
struct | 聲明結構體類型 |
chan | 聲明通道類型 |
else | if 語句的其他分支 |
goto | 無條件跳轉到指定標簽位置 |
package | 聲明包名 |
switch | 多分支選擇語句 |
const | 聲明常量 |
fallthrough | 使 switch 語句繼續執行下一個 case 分支,而不是跳出 switch 語句 |
if | 條件判斷語句 |
range | 用於遍曆數組、切片、字元串或映射的元素 |
type | 聲明自定義類型 |
continue | 跳過當前迴圈的剩餘部分,進入下一次迴圈 |
for | 迴圈語句 |
import | 導入外部包 |
return | 從函數返回 |
var | 聲明變數 |
Go 語言的 36 個預定義標識符
基本數據類型:
預定義標識符 | 說明 |
---|---|
bool | 布爾類型 |
byte | 位元組類型,等同於 uint8 |
complex64 | 64 位複數類型 |
complex128 | 128 位複數類型 |
error | 錯誤介面 |
float32 | 單精度浮點數類型 |
float64 | 雙精度浮點數類型 |
int | 有符號整數類型 |
int8 | 8 位有符號整數類型 |
int16 | 16 位有符號整數類型 |
int32 | 32 位有符號整數類型 |
int64 | 64 位有符號整數類型 |
rune | 字元類型,等同於 int32 |
string | 字元串類型 |
uint | 無符號整數類型 |
uint8 | 8 位無符號整數類型 |
uint16 | 16 位無符號整數類型 |
uint32 | 32 位無符號整數類型 |
uint64 | 64 位無符號整數類型 |
uintptr | 無符號整數指針類型 |
系統內置函數:
預定義標識符 | 說明 |
---|---|
make | 分配記憶體並初始化切片、映射或通道 |
new | 分配記憶體並初始化變數 |
panic | 引發運行時恐慌 |
recover | 從運行時恐慌中恢復 |
列印參數列表 | |
println | 列印參數列表並換行 |
預定義常量:
預定義標識符 | 說明 |
---|---|
true | 布爾類型的真值 |
false | 布爾類型的假值 |
iota | 用於常量計數器的特殊常量 |
nil | 零值指針 |
這些表格包含了 Go 語言的預定義標識符,包括基本數據類型、系統內置函數和預定義常量。在命名變數、函數或類型時,應避免使用這些預定義標識符。
轉義字元
轉義字元 | 定義 | 作用 |
---|---|---|
\\ | 反斜杠 | 表示一個反斜杠字元 |
\' | 單引號 | 表示一個單引號字元 |
\" | 雙引號 | 表示一個雙引號字元 |
\n | 換行符 | 在輸出中插入一個換行符 |
\r | 回車符 | 在輸出中插入一個回車符,使游標移動到行首 |
\t | 製表符(水平製表符) | 在輸出中插入一個製表符,用於對齊文本 |
\b | 退格符 | 在輸出中插入一個退格符,使游標回退一個字元位置 |
\f | 換頁符 | 在輸出中插入一個換頁符,使游標移動到下一頁 |
\v | 垂直製表符 | 在輸出中插入一個垂直製表符,用於垂直對齊文本 |
\ooo | 八進位編碼字元 | 表示一個八進位編碼的字元 |
\xhh | 十六進位編碼字元 | 表示一個十六進位編碼的字元 |
\uhhhh | Unicode 編碼字元 | 表示一個 Unicode 編碼的字元(16 位) |
\Uhhhhhhhh | Unicode 編碼字元 | 表示一個 Unicode 編碼的字元(32 位) |
示例
package main
import "fmt"
func main() {
// 演示轉義字元的用法
// \n 換行
fmt.Println("aaa\nbbb")
// \b 退格
fmt.Println("aaa\bbbb")
// \r 回車:游標回到本行的開頭,後續輸入會替換原有的字元
fmt.Println("aaaaa\rbbb")
// \t 製表符:水平製表符,用於對齊文本
fmt.Println("aaaaaaaaaaaaa")
fmt.Println("aaaaa\tbbbbb")
fmt.Println("aaaaaaaa\tbbbbb")
// \" 雙引號:表示一個雙引號字元
fmt.Println("\"Golang\"")
}
擴展:進位和進位轉換
在 Go 語言中,可以使用不同的進位表示整數,如二進位、八進位、十進位和十六進位。以下是各種進位表示的整數的示例:
- 二進位:以
0b
或0B
開頭,後跟二進位數字(0
和1
)。例如:0b1010
或0B1010
表示十進位數 10。 - 八進位:以
0
開頭,後跟八進位數字(0
到7
)。例如:012
表示十進位數 10。 - 十進位:直接寫十進位數字(
0
到9
)。例如:10
表示十進位數 10。 - 十六進位:以
0x
或0X
開頭,後跟十六進位數字(0
到9
,A
到F
或a
到f
)。例如:0xA
或0Xa
表示十進位數 10。
進位轉換
在 Go 語言中,可以使用 fmt.Printf()
或 strconv
包中的函數進行進位轉換。以下是一些示例:
package main
import (
"fmt"
"strconv"
)
func main() {
num := 42
// 十進位轉二進位
binStr := strconv.FormatInt(int64(num), 2)
fmt.Printf("Decimal %d to binary: %s\n", num, binStr)
// 十進位轉八進位
octStr := strconv.FormatInt(int64(num), 8)
fmt.Printf("Decimal %d to octal: %s\n", num, octStr)
// 十進位轉十六進位
hexStr := strconv.FormatInt(int64(num), 16)
fmt.Printf("Decimal %d to hexadecimal: %s\n", num, hexStr)
// 二進位轉十進位
binNum, _ := strconv.ParseInt("101010", 2, 0)
fmt.Printf("Binary 101010 to decimal: %d\n", binNum)
// 八進位轉十進位
octNum, _ := strconv.ParseInt("52", 8, 0)
fmt.Printf("Octal 52 to decimal: %d\n", octNum)
// 十六進位轉十進位
hexNum, _ := strconv.ParseInt("2A", 16, 0)
fmt.Printf("Hexadecimal 2A to decimal: %d\n", hexNum)
}
在這個示例中,我們使用了 strconv.FormatInt()
和 strconv.ParseInt()
函數進行進位轉換。這些函數可以根據需要將整數在不同進位之間進行轉換。註意,strconv.ParseInt()
函數在轉換過程中可能會發生錯誤(例如,無效的輸入或溢出),因此需要檢查返回的錯誤。
合抱之木,生於毫末;九層之台,起於累土;千里之行,始於足下。