类型系统是一个语言的类型体系结构,一个典型的类包含以下内容
基础类型: 如byte,int, bool等
复合类型: 如数组,结构体,指针等
可以只想任意对象的类型
值和引用语义
面向对象
接口
Go语言中的大多数类型都是值语义,并且都可以包含对应的操作。
你可以给任何类型 增加 方法。
在实现接口是,不需要从该接口继承,只需要实现该接口要求的所有方法就可以了。
任意类型都可以被 Any 类型引用。Any类型就是空接口 即 interface()
值语义和引用语义
二者的区别在于赋值,如:
b = a
b.Modify()
# 如果 b 的修改不会影 a ,这个类型就属于 值类型, 如果会影响 a ,这个类型就是引用类型
# Go 语言中的大多数类型都是 值语义 ,包括 基本类型,复合类型,最典型的就是 数组。
Go语言中有4个类型比较特别,看起来像引用语义,但是这不影响我们将 Go语言类型看成 值语义
数组切片:
map
channel: (goroutine)间的同学设施
接口(interface)
# 这几种类型都使用了指针,
结构体 (struct类型)
Go 语言的结构体放弃了很多的对象特征,只保留了组合(composition)这个最基本的特征。
// 声明很简单,如下,包含了两个属性,一个string,一个int
tpye person struct {
name string
age int
}
// 使用办法
var P person // P 现在就是struct类型的变量
P.name = "Any"
P.age = 20
fmt.Printf("The Person's name is %s",P.name)
# 这种P的声明,还可以用其他方式,如b
按顺序提供初始化值
P := person("fitch",24)
通过 fields:value 方式声明,这种声明,可以任意顺序
P := person(age:24, name:"fitch")
使用new ,这里 P 的类型是person
P := new(person)
struct 匿名函数
Go 支持只提供类型,不谢字段名的方式。这种方式称为匿名字段,也称为嵌入字段。
当匿名字段是一个struct的时候,这个struct所拥有的全部字段被隐式的引入了。
package main
import "fmt"
tpye Human struct{
name string
age string
weight int
}
type Student struct{
// 这里的Human 就是匿名函数
Human
tech string
}
func main(){
// 初始化
mark := Student(Human("Tom",20,120), "Computer Science"
// 访问相应字段 Human有的字段,全部被Student所引入
fmt.Printf("HIs name is: %s", mark.name)
fmt。Printf("His age is: %s", mark.age)
fmt.Printf("His weight is: %s", mark.weight)
fmt.Printf("His tech is: %s", mark.tech)
// modify tech info
mark.tech = "AI"
fmt.Printf("Tom changed his tech")
fmt.Printf("Tom's tech is:%s", mark.tech)
// modify weight info
fmt.Printf("Tom is not an athlet anymore")
mark.weight += 60
fmt.Printf("Tom's weight is: %s", mark.weight)
}
# Student 还可以访问 Human 这个字段作为字段名称
mark.Human = Human("Fitch", 23, 150)
mark.Human.age -= 1
通过匿名访问和修改字段是很有用的,当然,不只是struct 字段,其实,所有的内置函数和自定义类型都是可以作为匿名字段的。
package main
import "fmt"
// 自定义类型
type sKills []string
type Human struct{
name string
age int
weight int
}
type Student struct{
Human
// 自定义类型
sKills
// 内置函数
int
tech string
}
func main(){
fitch := Student(Human("Fitch", 34, 170), "Jave")
// 访问相应字段
fmt.Printf("HIs name is: %s", fitch.name)
fmt。Printf("His age is: %s", fitch.age)
fmt.Printf("His weight is: %s", fitch.weight)
fmt.Printf("His tech is: %s", fitch.tech)
// modify sKills
fitch.sKills = []string{"antomy"}
fmt.Printf("His sKills is: %s", fitch.sKills )
fmt。Printf("Fitch acquired tow new ones")
fitch.sKills = append(fitch.sKills, "Go", "Python")
fmt.Printf("Fitch's sKills is: %s", fitch.sKills)
// modify int
fitch.int = 3
fmt。Printf("Fitch's preferred number = %d", fitch.int)
}
上面两个匿名函数的调用,所用包含的字段都是不同的,如果几个函数都包含了同一个字段,要如何处理呢
// 如 上例中的 Human Student 都包含了Address 如何访问呢
// Go 的设定是最外层优先,如果你通过Student.Address 访问的时候,访问的是Student里的,不是Human里的。
// 如果要访问Human里的,要用: Student.Human.Address
fmt。Printf("Fitch's Address is: %s", fitch.Address)
// 访问Human里的字段
fmt.Printf("Fitch's Address is: %s", fitch.Human.Address)
其他示例
# 官方示例
// An empty struct.
struct {} // 空结构体
// A struct with 6 fields. // 6个域 包括 空域
struct {
x, y int // 定义了两个域 x、y,类型都是int,这就是 IdentifierList 了
u float32
_ float32 // padding // 空域,下划线
A *[]int // 定义一个 名称为 A 的 整形数组的指针
F func() // 定义一个 名称为 F 的 函数类型 域——无参数、无返回类型
}