本篇文章深入探討了 Go 語言中類型確定值、類型不確定值以及對應類型轉換的知識點,後續充分解析了常量與變數及其高級用法,並舉出豐富的案例。 關註公眾號【TechLeadCloud】,分享互聯網架構、雲服務技術的全維度知識。作者擁有10+年互聯網服務架構、AI產品研發經驗、團隊管理經驗,同濟本復旦碩, ...
本篇文章深入探討了 Go 語言中類型確定值、類型不確定值以及對應類型轉換的知識點,後續充分解析了常量與變數及其高級用法,並舉出豐富的案例。
關註公眾號【TechLeadCloud】,分享互聯網架構、雲服務技術的全維度知識。作者擁有10+年互聯網服務架構、AI產品研發經驗、團隊管理經驗,同濟本復旦碩,復旦機器人智能實驗室成員,阿裡雲認證的資深架構師,項目管理專業人士,上億營收AI產品研發負責人。
一、類型確定值
類型確定值是與特定數據類型明確綁定的。類型確定值在 Go 中占有很大一部分領域,包括但不限於常量、變數、函數返回值、結構體欄位等。下麵是對類型確定值的的示例:
類型確定值在變數聲明中
當你在變數聲明中明確指定了類型,那麼這個變數就是類型確定值。
var x int = 10 // x 是類型確定值,類型為 int
var y string = "Hello" // y 是類型確定值,類型為 string
類型確定值在函數返回值中
函數也可以返回類型確定值。
func sum(a int, b int) int { // 返回值類型明確為 int
return a + b
}
類型確定值在結構體欄位中
結構體欄位也是類型確定值。
type Person struct {
Name string // Name 是類型確定值,類型為 string
Age int // Age 是類型確定值,類型為 int
}
類型確定值在數組和切片中
數組和切片的元素也是類型確定值。
var arr [3]int = [3]int{1, 2, 3} // arr 是類型確定值,類型為 [3]int
var s []string = []string{"a", "b", "c"} // s 是類型確定值,類型為 []string
類型確定值在介面和類型斷言中
當你通過類型斷言將介面值轉換為某個具體類型時,結果是類型確定值。
var i interface{} = "this is string"
str, ok := i.(string) // str 是類型確定值,類型為 string
類型確定值在類型別名和自定義類型中
即使你創建了一個類型別名或自定義類型,實際上還是與原始類型綁定的類型確定值。
type Length int
var l Length = 10 // l 是類型確定值,類型為 Length
這些例子展示了類型確定值如何滲透到 Go 語言的各個方面,為開發者提供了嚴格的類型安全性。在編寫代碼時,對類型有明確的瞭解可以幫助你編寫更健壯、更安全的程式。
二、類型不確定值
類型不確定值是沒有明確類型的值。這些值不是與任何具體的數據類型綁定的,因此在編譯時,Go 編譯器會根據上下文來推斷其類型。在 Go 中,類型不確定值是一個相當有趣和多面性的概念。這些值存在於常量聲明、算術運算、以及一些內建函數中。下麵是對類型不確定值的的示例:
在算術運算中的類型不確定值
當你使用類型不確定值進行算術運算時,結果也是類型不確定值,除非運算中有一個類型確定值,這種情況下,結果將是類型確定值。
const c = 3 // 類型不確定值
var d int = 2 // 類型確定值
// e 依然是類型不確定值,因為參與運算的兩個值都是類型不確定值
const e = c * c
// f 是類型確定值,因為參與運算的有一個類型確定值
var f = c * d
在內建函數中的類型不確定值
一些 Go 的內建函數(如 len
)返回類型不確定值。
const s = "hello world"
const l = len(s) // l 是類型不確定值
類型不確定值與預設類型
每個類型不確定值都有一個與之關聯的預設類型,通常是基於字面量或者運算表達式。
const g = 42.0 // 預設類型是 float64
const h = 'x' // 預設類型是 rune
類型不確定值在數組長度聲明中
在數組長度聲明中也可使用類型不確定值。
const size = 4
var arr [size]int // 編譯器推斷 size 為 int
類型不確定值與 iota
iota
也是類型不確定值,經常用於枚舉。
const (
zero = iota // zero 是 0
one // one 是 1
)
三、顯式類型轉換與類型推斷
在 Go 語言中,類型轉換和類型推斷是兩個相當重要的概念。它們共同定義瞭如何在編譯和運行時處理不同類型的值。我們將詳細討論這兩個概念,並通過示例來闡明其用法和重要性。
顯式類型轉換
顯式類型轉換是通過語法明確地將一個數據類型轉換為另一個數據類型的操作。
定義
在 Go 中,顯式類型轉換的語法是 T(v)
,其中 T
是目標類型,而 v
是要轉換的值。
var x float64 = 42.0
var y int = int(x) // 顯式地將 float64 轉換為 int
限制與約束
顯式類型轉換並不總是有效的。轉換的合法性取決於源類型和目標類型。例如,不能直接將一個結構體類型轉換為整數或者浮點數。
type myStruct struct {
field int
}
var a myStruct
// var b int = int(a) // 這是不合法的
類型推斷
類型推斷是編譯器自動推斷變數類型的過程。在 Go 中,這通常發生在使用 :=
進行變數初始化時。
定義
當使用 :=
操作符聲明變數但沒有明確指定類型時,Go 編譯器會根據右側表達式的類型來推斷變數的類型。
z := 42 // 類型被推斷為 int
在複雜表達式中的類型推斷
在涉及多種類型的複雜表達式中,Go 會儘量進行類型推斷以滿足表達式的類型需要。
var m float64 = 3.14
n := int(m) + 42 // int(m) 顯式轉換,結果類型推斷為 int
類型推斷與類型不確定值
類型推斷也適用於類型不確定值。編譯器會根據上下文來推斷其最合適的類型。
const p = 5 // 類型不確定值
var q = p // 類型推斷為 int,因為 p 的預設類型是 int
四、常量
在 Go 語言中,常量(Constant)是不可改變的值,這一點與變數有明顯區別。一旦一個常量被定義,它的值就不能再被改變。常量可以是類型不確定值或類型確定值。
類型不確定常量
類型不確定常量是沒有明確類型的常量。這些常量不是與任何具體的數據類型綁定的,因此在編譯時,Go 編譯器會根據上下文來推斷其類型。
const a = 42 // a 是類型不確定值,因為沒有明確指定類型
類型確定常量
類型確定常量是與特定數據類型明確綁定的常量。
const c int = 42 // c 是類型確定值,因為其類型明確為 int
常量聲明中的自動補全
在常量聲明塊中,你可以省略後續常量的類型和值,它們會自動補全。
const (
x int = 10
y // y 也是 int 類型,值為 10
)
使用 iota
在常量聲明中
iota
是一個特殊的常量生成器,主要用於創建一組遞增的整數常量。
const (
zero = iota // zero 的值為 0
one // one 的值為 1
two // two 的值為 2
)
常量的可見性和可定址性
常量可以是導出或非導出的,取決於它的名稱是否以大寫字母開頭。常量不是可定址的。
const ExportedConst = "I am visible" // 可導出的常量
const unExportedConst = "I am not visible" // 不可導出的常量
常量溢出和預設類型
一個類型不確定常量所表示的值可能會溢出其預設類型。在這種情況下,只有當這個常量被用於一個可以容納該值的上下文時,編譯才會成功。
const big = 1 << 100 // 預設類型為 int,但值會溢出
var bigInt = big >> 99 // big 被用於一個 int64 上下文,沒有溢出
字元串常量
字元串常量是包含在雙引號中的一系列字元。
const hello = "Hello, world!"
布爾常量
布爾常量只有兩個可能的值:true
和 false
。
const flagTrue = true
const flagFalse = false
枚舉常量
通過使用 iota
,你可以創建一組遞增的整數常量,通常用於枚舉。
type Weekday int
const (
Sunday Weekday = iota
Monday
Tuesday
// ...
Saturday
)
複數常量
Go 支持複數類型,並且你可以創建複數常量。
const complexConst = 1 + 2i
強制類型轉換
你可以通過強制類型轉換將一個常量轉換為另一種類型。
const integer = 42
const floatType = float32(integer)
計算表達式中的常量
常量也可以是計算表達式的結果,但表達式必須只包含常量值。
const calculated = 3 * 2 // 6
常量數組和切片
需要註意的是,在 Go 中,數組大小需要是常量。但切片和映射的大小可以動態改變,因此它們不能是常量。
const arraySize = 5
var arr [arraySize]int // 合法
五、變數
變數是存儲數據值的存儲單元,其值可以在運行時改變。在 Go 語言中,變數的使用非常靈活但又具有嚴格的類型安全性。
變數聲明和賦值
基本聲明
使用 var
關鍵字進行變數聲明。
var x int
同時聲明和賦值
var y int = 42
或者使用短變數聲明形式:
z := 42
多變數聲明
var a, b, c int
或者
var (
d int
e float64
)
類型描述
基本類型
包括 int
, float64
, bool
, string
等。
var integerVar int = 10
var floatVar float64 = 10.99
var boolVar bool = true
var stringVar string = "Hello, Go"
數值類型
Go 支持多種數值類型,包括 int8
, int16
, int32
, int64
, uint8
, uint16
, uint32
, uint64
, float32
, float64
等。
var smallInt int8 = 127
var largeInt int64 = 9223372036854775807
var unsignedInt uint16 = 65535
var floatNum float32 = 3.141592
字元和字元串
Go 有 rune
和 byte
類型來表示 Unicode 字元和 ASCII 字元。
var asciiChar byte = 'A'
var unicodeChar rune = '你'
var str string = "Hello, World!"
布爾類型
布爾類型只有兩個值:true
和 false
。
var isActive bool = true
var isCompleted bool = false
指針
Go 支持指針類型,但不支持指針運算。
var pointer *int
x := 42
pointer = &x
數組和切片
var arrayExample [5]int = [5]int{1, 2, 3, 4, 5}
var sliceExample []int = arrayExample[1:4]
映射(Maps)
var countryCapitalMap map[string]string
countryCapitalMap = make(map[string]string)
countryCapitalMap["France"] = "Paris"
結構體(Structs)
type Employee struct {
ID int
Name string
Salary float64
}
var emp Employee
介面(Interfaces)
type Shape interface {
Area() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
var s Shape = Circle{5.0}
函數類型
Go 中,函數也是一種類型,可以作為參數傳遞。
type AddFunc func(a int, b int) int
var add AddFunc = func(a int, b int) int {
return a + b
}
通道(Channels)
var messageChannel chan string = make(chan string)
複合類型
例如數組、切片、映射、通道、結構體和介面。
數組
var arr [5]int
切片
var slice []int
映射
var mapping map[string]int
通道
var ch chan int
結構體
type Person struct {
name string
age int
}
var p Person
介面
type Geometry interface {
Area() float64
}
var g Geometry
值的可定址性
Go 語言中有些變數是可定址的,意味著你可以獲取這個變數的記憶體地址。
var myVar int = 42
var p *int = &myVar
變數作用域
在 Go 中,變數可以有不同的作用域:全局作用域、包內作用域、函數作用域、代碼塊作用域等。
var globalVar int // 全局作用域
func myFunction() {
var functionVar int // 函數作用域
{
var blockVar int // 代碼塊作用域
}
}
七、常量和變數的高級用法
在 Go 編程中,常量和變數不僅僅是數據存儲的簡單方式。它們有各種高級用法,可以用來優化代碼、提高效率或實現複雜的編程模式。
常量的高級用法
枚舉和 iota
Go 通過 iota
關鍵字支持枚舉類型的實現。這在一組常量聲明中是非常有用的。
const (
Monday = iota + 1 // Monday = 1
Tuesday // Tuesday = 2
Wednesday // Wednesday = 3
)
類型別名
使用類型別名,你可以將常量限製為自定義類型。
type Weekday int
const (
Sunday Weekday = iota
Monday
// ...
)
無類型和有類型常量
無類型的常量可以用在多種場合,它們會根據上下文進行類型推斷。
const x = 42 // 無類型常量
var i int = x
var f float64 = x
變數的高級用法
變數的作用域
Go 支持塊級作用域。通過 var
關鍵字在不同級別(全局、包級別、函數級別等)聲明變數,你可以控制變數的可見性。
var globalVar = 42 // 全局變數
func main() {
var funcVar = "I'm local" // 函數級別變數
}
延遲初始化
使用 init()
函數,你可以在程式開始執行前初始化變數。
var complexVar complex128
func init() {
complexVar = cmplx.Sqrt(-5 + 12i)
}
指針和地址操作符
雖然 Go 語言沒有提供指針運算,但它允許你通過地址操作符 &
和解引用操作符 *
來操作指針。
x := 42
p := &x
fmt.Println(*p) // 輸出 42
使用標簽(Tags)和結構體
在結構體中,你可以使用標簽(tags)來附加元數據,這在序列化和反序列化時非常有用。
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
關註公眾號【TechLeadCloud】,分享互聯網架構、雲服務技術的全維度知識。作者擁有10+年互聯網服務架構、AI產品研發經驗、團隊管理經驗,同濟本復旦碩,復旦機器人智能實驗室成員,阿裡雲認證的資深架構師,項目管理專業人士,上億營收AI產品研發負責人。
如有幫助,請多關註
個人微信公眾號:【TechLeadCloud】分享AI與雲服務研發的全維度知識,談談我作為TechLead對技術的獨特洞察。
TeahLead KrisChang,10+年的互聯網和人工智慧從業經驗,10年+技術和業務團隊管理經驗,同濟軟體工程本科,復旦工程管理碩士,阿裡雲認證雲服務資深架構師,上億營收AI產品業務負責人。