golang 有哪些数据类型
interface 是一种数据类型吗,答案是:是。
golang 语言有四种数据类型,分别是
- 基本类型(basic)
- 数字
- 字符串
- 布尔型
- 聚合类型(aggregate)
- 数组
- struct
- 复合类型(reference)
- 指针
- slice
- map
- 函数
- channel
- 接口类型(interface)
什么是方法
方法是定义在一个数据类型上面的函数,可以类比为 “面向对象中,类中的方法”。
方法和这个数据类型需要处于同一个包里,所以对于内置类型,如 int,需要从他定义一个数据类型,
type CountNum int
然后再在这个新的数据类型上定义方法
func (c CountNum) Print {
fmt.Printf("CountNum is %d", i)
}
最常用的就是在 struct 上定义方法
type Person struct {
Name string
Age int
}
func (p Person) Get {
return fmt.Sprintf("Person name: %6s, age: %4d", p.Name, p.Age)
}
使用方法修改所定义的数据类型的数据
func (p Person) Set(name string) {
p.Name = name
}
如果直接这么写,是有问题的。
因为在 golang 中是参数是值传递,所以在上面这个方法里,收到了类型为Person
的一个值的拷贝p
,然后对p
做了修改,是无法传递出去的。
所以需要改为传递指针变量:
func (p *Person) Set(name string) {
p.Name = name
}
这样就可以通过指针修改原来的数据。
事实上,指针仍然是值传递,但是,哈哈,拷贝的指针指向的地方是不变的,是依然可以修改的。
怎么定义一个 interface
划重点:接口的定义是方法的声明的集合,接口的实现是方法的实现的集合
所以我刚刚先说了方法。
和方法不一样的是,接口并不是定义在具体的类型上面的(方法是这样的)。
同一个接口可以在不同数据类型上实现,取决于你想要怎么搞了。
这里我先定义一个接口:
type GetSet interface {
Get() string
Set(string)
}
这个接口声明了两个方法:Get() string
,Set(string)
,这两个方法合起来(interface{ }
)就构成了一个接口,这个接口的名字叫做GetSet
。
怎么实现一个 interface
说明
golang 这门语言的接口与其他语言的不同之处在于,golang 的接口是隐式实现
的。
这是什么意思呢?
意思就是你不需要显式
的这么做:
class SomeClass implements SomeInterface {
}
那怎么做
刚刚说了:「接口的实现是方法的实现的集合」,方法是定义在数据类型上面的,所以先给出一个数据类型:
type Person struct {
Name string
Age int
}
然后对这个数据类型实现接口定义里面所有声明的方法,也就是:Get() string
,Set(string)
func (p *Person) Get() string {
return fmt.Sprintf("Person name: %6s, age: %4d", p.Name, p.Age)
}
func (p *Person) Set(name string) {
p.Name = name
}
断言是否实现了接口
ok,到这里为止,我定义了一个接口GetSet
,然后用Person
实现了这个接口,一切都很美好,问题是,我真的实现了这个接口了吗?
有一个简单的方法去判断:
var _ GetSet = new(Person) // var _ GetSet = Person{}
这是一个断言:Person
的一个值实现了接口GetSet
,如果Person
没有实现了接口GetSet
,编译的时候就会报错。
实际上,我们不需要创建一个变量(new(Person)
),因为Person
是任意值都实现了这个接口,所以nil
也实现了,所以可以用类型转化做断言,代码如下:
var _ GetSet = (*Person)(nil)
空 interface 是什么
什么是空接口:
interface{}
上面说过,接口是声明的方法的集合,空接口没有声明方法,所以任何类型都实现了空接口。
所以一个函数可以使用interface{}
接受任意类型的值作为参数,也可以使用interface{}
将任意类型的值作为返回值。