type的分类
按结构:
- 基础类型,pre-declarered types:boolean,numeric and string
- 复合类型,composite types:array,struct,map,slice,channel,func,interface 等
按名称:
- Named Types:用type关键字定义,以及基础类型
- Unamed types:是一个 literal type,也就是没有名字,只有 type 本身,像这样
[6]int
没有名字
underlying type:每一个类型都有自己的 underlying type ,如果 T 是 pre-declared type 或者 type literal,它们对应的 underlying type 就是自身 T,否则 T 的 underlying type 是T 定义时引用的类型的 underlying type
Underlying type 相同的 type
如果两个 type 的 underlying type 相同,则它们可以有以下特性:
- 如果两个 type 都是 named type ,彼此之间不能相互赋值
- 如果两个 type 其中一个是 unnamed type,彼此之间可以相互赋值
如果为一个类型起了名字,说明你想要做区分,所以两个 named types 即使 underlying name 相同也是不能相互赋值的
Named type 和 Unamed type 不同
当 named types 被作为一个 function 的 receiver 时,它就拥有了自己的方法,unamed types 则不能,这是它们的重要区别,pre-declare types 不能拥有自己的方法。
type 的属性继承一:直接继承
Declared named type 不会从它的 underlying type 或 existing type 继承 method,但是会继承 field。
例外:
- 如果 existing type 是 interface,它的 method set 会被继承
- 如果 existing type 是 composite type,method也会被继承(如下?)
type 的属性继承二:type embedding
如果一个 type T‘ 被嵌入另一个 type T 作为它的 filed,T’ 的所有 field 和 method 都可以在 T 中使用,这种方法称之为 type embedding
由于内部类型的提升,内部类型实现的接口会自动提升到外部类型。这意味着由于内部类型的
实现,外部类型也同样实现了这个接口。如果外部类型实现了 notify 方法,内部类型的实现就不会被提升。不过内部类型的值一直存在,因此还可以
通过直接访问内部类型的值,来调用没有被提升的内部类型实现的方法。(《goinaction》)
type 转换
Type 之间是可以相互转换的,但要遵循一定的转换规则,详细请看官方规范 https://golang.org/ref/spec#Conversions。
关于接口
Go的类型系统的核心概念:我们不是根据我们的类型可以容纳的数据来设计抽象,而是根据我们的类型可以执行的操作来设计抽象。
定义一个接口:任何有Speak() string
方法的类型都是动物(Animal)
type Animal interface {
Speak() string
}
如dog结构类型:
type Dog struct {
}
func (d Dog) Speak() string {
return "Woof!"
}
cat结构类型:
type Cat struct {
}
func (c Cat) Speak() string {
return "Meow!"
}
方法调用
func main() {
//创建一个Animal接口类型的切片并用满足该接口的结构类型进行初始化
animals := []Animal{Dog{}, Cat{}}
//遍历该切片
for _, animal := range animals {
调用该结构类型的方法
fmt.Println(animal.Speak())
}
}
所有类型都满足空接口。这意味着如果您编写一个将interface{}
值作为参数的函数,则可以为该函数提供任何值。
func DoSomething(v interface{}){
// ...
}
将接受任何参数。
v不是任何类型,v不属于任何类型,v是interface{}
类型
所有值在运行时都只有一种类型,v的静态类型是interface{}
回到最初的例子,animals切片内的每个元素都是Animal类型,但不同值具有不同的基础类型
[]string
的值是不能作为参数传入需要[]interface{}
类型的函数的,需要经过如下转换(并不常用)
names:= [] string {“stanley “,”david“,”oscar“}
vals:= make([] interface {},len(names))
for i,v:= range names {
vals [i] = v
[How to use interfaces in Go](How to use interfaces in Go) 还没看完