作者:wuyunhua | 2023-10-08
很多新手对& * [] {}的组合感到困惑,不知道什么时候该用什么,这是因为对 go 类型系统不够了解,本文主要讲解go类型系统的基础知识,帮助大家理解go类型系统。
一些类型的例子
type MyInt int // int类型
type MyIntPtr *int // int指针类型
type Book struct {} // 结构体类型
type Option func(int) int // 函数类型
type Name []byte // 切片类型
type Sigal chan<- int // 通道类型
type Object interface{} // 接口类型
一个类型的一个实例称为此类型的一个值,一个类型可以有很多不同的值,其中一个为它的零值
基本类型可以直接用来申明变量,而组合类型不可以,官方把这种可以直接定义变量的类型叫defined type,而不能直接定义变量的类型叫undefined type
// 一个变量的类型是int
var MyInt int
// 无法说一个变量是容器类型
var MySlice 容器类型?
// 需指定具体是什么类型的容器
var MySlice []int
所有类型都有底层类型 underlying type
法则:在溯源过程中,当遇到一个内置类型或者undefined type时,溯源结束
// 类型MyInt的底层类型是int
type MyInt int
// 类型YourInt的底层类型是int
type YourInt MyInt
// 类型Book的底层类型是struct{}
type Book struct{}
// 类型Name的底层类型是[]MyInt
type Name []MyInt
// 类型Nickname的底层类型是[]MyInt
type Nickname Name
type Student []byte
type Teacher []byte
var stu Student = []byte{'a'}
var tea Teacher = []byte{'b'}
// 这是不可以的
stu = tea
tea = stu
// 这是可以的
stu = Student(tea)
tea = Teacher(stu)
也服从上述规则,但额外多出一条,如果指针类型的底层类型不同,但基类型相同,可以显示转换
type MyInt int
type IntPtr *int
type MyIntPtr *MyInt
var a *int = new(int)
var b IntPtr
// 这是可以的
a = b
b = a
var c MyIntPtr
// 这是不可以的
a = c
c = a
var d *MyInt
// 这是可以的
d = (*MyInt)(a)
不服从上述规则,如果类型T实现了接口I,则T类型的值都可以隐式转换为类型I
type Book interface{
Name() string
}
type EnglishBook struct {}
func(b *EngilishBook) Name() string {
return "english book"
}
var ebook *EnglishBook = &EnglishBook{}
var book Book
// 这是可以的
book = ebook
有一个特殊情况,如果接口的方法集是空,意味着任意类型都实现了这个空接口,则可以发生上述隐式转换
type EnglishBook struct {}
func(b *EngilishBook) Name() string {
return "english book"
}
var ebook = &EnglishBook{}
var book interface{}
// 这是可以的
book = ebook
var age int = 1
var myage interface{}
// 这是可以的
myage = age
这就是go中著名的万金油类型interface{},如果你不知道变量是什么类型,就用interface{}
var a interface{}
a = 1
// 这是可以的
b := a.(int)
// 这会panic
b := a.(int32)
// 如果有第二个参数,第二个参数是bool类型,永不panic
b, ok := a.(int)
type Book struct{
name string
}
var v interface{} = &Book{name:"book"}
// t是类型值,v是接口值
switch t := v.(type) {
case string:
return ""
case int,int32,int64:
return fmt.Sprint(t)
case Book:
return t.name
default:
return ""
}
var a []*Member // 结构体指针的切片
var b *[]Member // 结构体切片的指针
c := []*Member{} // 结构体指针的切片初始化
d := &[]Member{} // 结构体切片的指针初始化
var e []*[]*Member // 结构体切片的指针的切片
var f *[][]*Member // 结构体切片的切片的指针
g := []*[]*Member{} // 结构体切片的指针的切片初始化
h := &[][]*Member{} // 结构体切片的切片的指针初始化
类型系统很重要,不会类型系统,写代码寸步难行。建议阅读官方的类型系统原文。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.wuyunhua.cn/golang-types