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]]
}
posted @ 2022-02-06 21:07  ArtiaDeng  阅读(323)  评论(0)    收藏  举报