golang的结构体 方法 接口
结构体,方法和接口
1. 结构体(struct) 和方法(methods)
结构体类似于其他语言中的 class,可以在结构体中定义多个字段,为结构体实现方法,实例化等。接下来我们定义一个结构体 Student,并为 Student 添加 name,age 字段,并实现 hello() 方法。
type Student struct {
name string
age int
}
func (stu *Student) hello(person string) string {
return fmt.Sprintf("hello %s, I am %s", person, stu.name)
}
func main() {
stu := &Student{
name: "Tom",
}
msg := stu.hello("Jack")
fmt.Println(msg) // hello Jack, I am Tom
}
- 使用
Student{field: value, ...}的形式创建 Student 的实例,字段不需要每个都赋值,没有显性赋值的变量将被赋予默认值,例如 age 将被赋予默认值 0。 - 实现方法与实现函数的区别在于,
func和函数名hello之间,加上该方法对应的实例名stu及其类型*Student,可以通过实例名访问该实例的字段name和其他方法了。 - 调用方法通过
实例名.方法名(参数)的方式。
除此之外,还可以使用 new 实例化:
func main() {
stu2 := new(Student)
fmt.Println(stu2.hello("Alice")) // hello Alice, I am , name 被赋予默认值""
}
2. 接口(interfaces)
一般而言,接口定义了一组方法的集合,接口不能被实例化,一个类型可以实现多个接口。
举一个简单的例子,定义一个接口 Person和对应的方法 getName() 和 getAge():
type Person interface {
getName() string
}
type Student struct {
name string
age int
}
func (stu *Student) getName() string {
return stu.name
}
type Worker struct {
name string
gender string
}
func (w *Worker) getName() string {
return w.name
}
func main() {
var p Person = &Student{
name: "Tom",
age: 18,
}
fmt.Println(p.getName()) // Tom
}
- Go 语言中,并不需要显式地声明实现了哪一个接口,只需要直接实现该接口对应的方法即可。
- 实例化
Student后,强制类型转换为接口类型 Person。
在上面的例子中,我们在 main 函数中尝试将 Student 实例类型转换为 Person,如果 Student 没有完全实现 Person 的方法,比如我们将 (*Student).getName() 删掉,编译时会出现如下报错信息。
*Student does not implement Person (missing getName method)
但是删除 (*Worker).getName() 程序并不会报错,因为我们并没有在 main 函数中使用。这种情况下我们如何确保某个类型实现了某个接口的所有方法呢?一般可以使用下面的方法进行检测,如果实现不完整,编译期将会报错。
var _ Person = (*Student)(nil)
var _ Person = (*Worker)(nil)
- 将空值 nil 转换为 *Student 类型,再转换为 Person 接口,如果转换失败,说明 Student 并没有实现 Person 接口的所有方法。
- Worker 同上。
实例可以强制类型转换为接口,接口也可以强制类型转换为实例。
func main() {
var p Person = &Student{
name: "Tom",
age: 18,
}
stu := p.(*Student) // 接口转为实例
fmt.Println(stu.getName())
}
3. 空接口
如果定义了一个没有任何方法的空接口,那么这个接口可以表示任意类型。例如
func main() {
m := make(map[string]interface{})
m["name"] = "Tom"
m["age"] = 18
m["scores"] = [3]int{98, 99, 85}
fmt.Println(m) // map[age:18 name:Tom scores:[98 99 85]]
}

浙公网安备 33010602011771号