类型系统是指一个语言的类型体系结构,一个典型的类型系统通常包含如下基本内容:
- 基础类型: byte、int、bool、float等
- 复合类型: 如数组、结构体、指针等;
- 可以指向任意对象的类型(Any类型)
- 值语义和引用语义
- 对象
- 接口
GO 是一种静态编译型语言,编译器需要在编译时知道每个值的类型,以便运行前检查,编译时优化代码。go允许用户自定义类型,有两种方式,最常用使用关键词struct
声明结构类型。
自定义类型
strunct
声明结构类型
例如s,声明一种类型user:
type user struct {
name string
email string
ext int
privileged bool
}
使用:
var zz user
声明user类型zz,并没有初始化,自动使用默认类型初始化,如:0,“”,false。也可以在声明时初始化,如下:
thoreau := user{
name: "thoreau",
email: "zz.thoreau@g.com",
ext:1,
privileged: false,
}
print thoreau –> {thoreau zz.thoreau@g.com 1 false}
上述初始化方式需要每个属性,也可以按照自动顺序初始化:
lisa := user{"Lisa", "lisa@email.com", 123, true}
fmt.Println(lisa)
结果:{Lisa lisa@email.com 123 true}
使用已有类型声明
基于一个已有的类型,将其作为新类型的类型说明,有点像类型赋值,但是,他们不是同一类型,不能相互赋值,下面的示例就会编译出错。
package main
type Duration int64
func main() {
var dur Duration
dur = int64(1000)
}
方法
方法能给用户定义的类型添加新的行为。方法实际上也是函数,只是在声明时,在关键字func 和方法之间加了一个参数。
关键字 func 和函数之间的参数被作接收者,将函数与接收者的类型绑在一起。如果一个函数有接收者,这个函数就被称为方法。
在Go语言中,你可以给任意类型(包括内置类型,但不包括指针类型)添加相应的方法。
package main
import (
"fmt"
)
func main() {
lisa := user{"Lisa", "lisa@email.com", 123, true}
lisa.printUser(",hello!")
fmt.Println(lisa.extLess100())
}
type user struct {
name string
email string
ext int
privileged bool
}
func (u user) printUser(s string) {
fmt.Println(u.name,s)
}
func (u user) extLess100() bool{
return u.ext < 100
}
Lisa ,hello! false
上面的示例表示,声明了一种类型user,有方法printUser和extLess100。可以看出有,跟java中类和方法的区别是,方法可以定义在类型外,方法需要指明类型绑定,返回值放到了最后。具体来说,方法绑定对象(接收者),函数只跟包有关系。
值接收者和指针接收者
go定义了两种接收者:值接收者和指针接收者,上面示例属于值接收者。使用值接收者,使用的其实是接收者的一个副本,任何操作都不会影响原来的类型变量。如果是指针传递,操作的是指针副本,但副本也指向同一个类型变量,所以会改变原来的类型,如下:
package main
import (
"fmt"
)
func main() {
p:=person{name:"go"}
p.modify() //值接收者,修改无效
fmt.Println(p.toString())
p.modifyOrigin()
fmt.Println(p.toString())
}
type person struct {
name string
}
func (p person) toString() string{
return "the person name is "+p.name
}
func (p person) modify(){
p.name = "thoreau"
}
func (p *person) modifyOrigin(){
p.name = "thoreau"
}
the person name is go the person name is thoreau
从结果看出,modify方法不改变原类型变量,但modifyOrigin改变了,区别就是使用了*persion
指针传递。
多值返回
和函数一样,方法支持多返回值
可变参数
函数方法的参数,可以是任意多个,这种我们称之为可以变参数。使用...
表示。
func main() {
fmt.Println(add(1, 2, 3))
fmt.Println(add(1, 2, 3, 4))
}
func add(x ... int) int {
var y int = 1
for _, v := range x {
y = y + v
}
return y
}
7 11