概述
Go语言中,struct是一个非常重要的概念,它既是一种数据类型,也可以结合方法(一种特殊的函数),构建类似于OOP的类。不多说,先上代码:
package main
import (
"fmt"
)
type A struct {
Name string
}
type B struct {
*A //匿名字段,以指针方式引用结构A
}
type C struct {
B //定义匿名字段,以值方式引用结构B
}
type Interfacer interface {
Get() string
Set(v string)
}
// 构建一个结构B
func NewB() *B {
var a = &A{}
return &B{A: a}
}
// 实现Interfacer中的Get
func (b *B) Get() string {
return b.A.Name
}
// 实现Interfacer中的Set
func (b *B) Set(v string) {
b.A.Name = v
}
func (b *B) Do() {
if b.A.Name == "" {
fmt.Println("Name is null.")
return
}
fmt.Printf("Hello, %s.\n", b.A.Name)
}
var _ Interfacer = new(B)
func TestImpl(i Interfacer) {
i.Set("changed")
fmt.Println("Get a name: " + i.Get())
}
func main() {
// 验证结构B
b1 := NewB()
b1.Do()
// 普通的赋值方法
b1.Name = "test"
b1.Do()
b2 := NewB()
b2.Set("sail")
b2.Do()
// 另一种结构赋值方法
b3 := B{A: &A{Name: "oly"}}
b3.Do()
TestImpl(&b3)
b3.Do()
var c C
c.A = &A{Name:"first"}
c.Name = "sam"
c.B.Do()
TestImpl(&c.B)
c.Set("other1")
c.Do()
c.B.Set("other2")
c.B.Do()
}
我的一些理解
这段代码中:
- 定义了A、B、C三个struct类型,一个Interfacer接口
- 结构A的作用主要是一个数据结构
- 结构B的作用相当于一个类,拥有Do()方法,并实现了Interfacer接口的Get和Set
- 结构C的作用相当于继承于B(B也相当于继承A)
- 结构B以指针的方式匿名引用了结构A,可以用
b.Name = "some_name"
来赋值 - 结构C以值的方式匿名引用了结构B,可以用
c.Do()
来调用B中的方法,由于B又匿名引用了A,还可以用c.Name = "sam"
来赋值 - 由于结构B是以
(b *B)
指针方式来实现接口Interfacer的,所以必须以指针方式来调用函数TestImpl(&b)
- golang与ruby类似,接口特性是ducking type,即“如果它走起来像鸭子,叫起来像鸭子(实现了接口要的方法),它就是一只鸭子(可以被赋值给接口的值)”。所以把&b作为参数传入到函数
TestImpl()
中,一点问题没有。
结论
Go语言虽然没有类的概念,但通过struct类型、匿名字段、方法和接口,简单地实现了类似于OOP中类、方法、继承等概念。
有疑问加站长微信联系(非本文作者)