掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
注意:本節(jié)內(nèi)容涉及Go語言新版本的功能,內(nèi)容上會涉及后續(xù)章節(jié)講解的類型定義及結(jié)構(gòu)體嵌入等特性。另外,本節(jié)內(nèi)容適用于對Go語言很熟悉且正在關(guān)注工程升級、代碼重構(gòu)等問題的讀者閱讀。

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)上虞免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了近1000家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
類型別名是 Go 1.9 版本添加的新功能,主要用于解決代碼升級、遷移中存在的類型兼容性問題。在 C/ C++ 語言中,代碼重構(gòu)升級可以使用宏快速定義一段新的代碼,Go語言中沒有選擇加入宏,而是解決了重構(gòu)中最麻煩的類型名變更問題。
在 Go 1.9 版本之前定義內(nèi)建類型的代碼是這樣寫的:
type byte uint8 type rune int32
而在 Go 1.9 版本之后變?yōu)椋?/p>
type byte = uint8 type rune = int32
這個修改就是配合類型別名而進(jìn)行的修改。
定義類型別名的寫法為:
type TypeAlias = Type
類型別名規(guī)定:TypeAlias 只是 Type 的別名,本質(zhì)上 TypeAlias 與 Type 是同一個類型,就像一個孩子小時候有小名、乳名,上學(xué)后用學(xué)名,英語老師又會給他起英文名,但這些名字都指的是他本人。
類型別名與類型定義表面上看只有一個等號的差異,那么它們之間實際的區(qū)別有哪些呢?下面通過一段代碼來理解。
package main
import (
"fmt"
)
// 將NewInt定義為int類型
type NewInt int
// 將int取一個別名叫IntAlias
type IntAlias = int
func main() {
// 將a聲明為NewInt類型
var a NewInt
// 查看a的類型名
fmt.Printf("a type: %T\n", a)
// 將a2聲明為IntAlias類型
var a2 IntAlias
// 查看a2的類型名
fmt.Printf("a2 type: %T\n", a2)
}代碼運行結(jié)果:
a type: main.NewInt
a2 type: int
代碼說明如下:
%T格式化參數(shù),打印變量 a 本身的類型。結(jié)果顯示 a 的類型是 main.NewInt,表示 main 包下定義的 NewInt 類型,a2 類型是 int,IntAlias 類型只會在代碼中存在,編譯完成時,不會有 IntAlias 類型。
能夠隨意地為各種類型起名字,是否意味著可以在自己包里為這些類型任意添加方法呢?參見下面的代碼演示:
package main
import (
"time"
)
// 定義time.Duration的別名為MyDuration
type MyDuration = time.Duration
// 為MyDuration添加一個函數(shù)
func (m MyDuration) EasySet(a string) {
}
func main() {
}代碼說明如下:
編譯上面代碼報錯,信息如下:
cannot define new methods on non-local type time.Duration
編譯器提示:不能在一個非本地的類型 time.Duration 上定義新方法,非本地類型指的就是 time.Duration 不是在 main 包中定義的,而是在 time 包中定義的,與 main 包不在同一個包中,因此不能為不在一個包中的類型定義方法。
解決這個問題有下面兩種方法:
當(dāng)類型別名作為結(jié)構(gòu)體嵌入的成員時會發(fā)生什么情況呢?請參考下面的代碼。
package main
import (
"fmt"
"reflect"
)
// 定義商標(biāo)結(jié)構(gòu)
type Brand struct {
}
// 為商標(biāo)結(jié)構(gòu)添加Show()方法
func (t Brand) Show() {
}
// 為Brand定義一個別名FakeBrand
type FakeBrand = Brand
// 定義車輛結(jié)構(gòu)
type Vehicle struct {
// 嵌入兩個結(jié)構(gòu)
FakeBrand
Brand
}
func main() {
// 聲明變量a為車輛類型
var a Vehicle
// 指定調(diào)用FakeBrand的Show
a.FakeBrand.Show()
// 取a的類型反射對象
ta := reflect.TypeOf(a)
// 遍歷a的所有成員
for i := 0; i < ta.NumField(); i++ {
// a的成員信息
f := ta.Field(i)
// 打印成員的字段名和類型
fmt.Printf("FieldName: %v, FieldType: %v\n", f.Name, f.Type.
Name())
}
}代碼輸出如下:
FieldName: FakeBrand, FieldType: Brand
FieldName: Brand, FieldType: Brand
代碼說明如下:
這個例子中,F(xiàn)akeBrand 是 Brand 的一個別名,在 Vehicle 中嵌入 FakeBrand 和 Brand 并不意味著嵌入兩個 Brand,F(xiàn)akeBrand 的類型會以名字的方式保留在 Vehicle 的成員中。
如果嘗試將第 33 行改為:
a.Show()
編譯器將發(fā)生報錯:
ambiguous selector a.Show
在調(diào)用 Show() 方法時,因為兩個類型都有 Show() 方法,會發(fā)生歧義,證明 FakeBrand 的本質(zhì)確實是 Brand 類型。

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流