创建 struct

在 Go 语言的结构体(struct)和其他语言的类(class)具有同等地位。但是绝对不是一个东西。我们尽量不要用过语言来翻译新的语言的某些语法。在 go 语言中放弃了继承而保留了组合。

type Person struct {
    name string
    age int
}

通过 type 关键字定义一个 struct ,struct 定义数据结构最早是在 c++ 中看到和了解到 struct 的。定义 struct 结构包括哪些属性,并且指定属性的类型,是以单行的形式声明的,大家可能注意到了其结尾没有逗号分隔。
首字母大写在 go 语言中有着特殊含义

如何实例化 struct

p1 := new(Person)
p2 := &Person{}
p3 := &Person{
        name: "zidea",
        age: 35,
    }
    p := Person{
        "zidea",
        35,
    }

实例化 Person 很简单,struct 名称后面紧跟一对花括号,在花括号中定义名称。然后可以通过(.)来调用对象 p 的属性。

在 go 语言中显式初始化的变量都会被初始化为该类型的零值。在 Go 语言中没有构造函数的概念,对象的创建通常交给由一个全局的创建函数来完成,以 NewXXX 来命名,表示“构造函数”。

func NewPerson(name string,age number) *Person{
    return &Person{name,age}
}

p.name= "zidea"
type Person struct{
    name string
    tuts []string
    age int
}

当为 Person 添加字段 tuts 这时如果没有更新 p 就会在编译时候发生错误

/main.go:31:3: cannot use 35 (type int) as type []string in field value
./main.go:31:3: too few values in Person literal

但是当我们显示地进行赋值就不会发生这样错误。

在 go 语言属性名称首字母大写是有特殊意义,首字母大写表示该字段在其他 package 是可以访问到该属性,类似 java 中 public。

type Person struct{
    Name string
    Tuts []string
    Age int
}

struct 是可以进行嵌套的

type person struct {
    name    string
    age     int
    contact struct {
        phone, city string
    }
}

字面量初始化

也可以通过字面值进行初始化,这是常用的做法,写法类似于JSON的写法

type Person struct {
    name string
    age int
}

p := Person{
        name:"zidea",
        age: 30,
    }

结构体作为参数传递

定义函数接受参数为 Person 注意在 go 默认是传值的

func print(p Person){
    fmt.Println(p.name)
    fmt.Println(p.age)
}
print(p)

结构体指针

如果要在函数 print 中修改作为参数传入的 person 对象,就需要传地址而非传值

 p := &Person{
        name:"zidea",
        age: 30,
    }
func print(p *Person){
    fmt.Println(p.name)
    fmt.Println(p.age)
}

匿名结构体

  a := &struct{
        name string
        age int
    }{
        name:"zidea",
        age: 30,
    }

结构体的继承

在 go 语言中放弃了继承而保留了组合,而这种组合是匿名的,也称为匿名组合。

type Base struct{
    Name string
}

func (base *Base) Foo(){
    fmt.Println("call Foo method of Base")
}
func (base *Base) Bar(){
    fmt.Println("call Bar method of Base")
}

type Foo struct{
    Base
}

func (foo *Foo) Bar(){
    fmt.Println("call Bar method of Foo")
    foo.Base.Bar()
}

func main() {
    f := Foo{}
    f.Bar()
}

上面代码定义了 Base 基类,为 Base 基类添加两个方法 Foo 和 Bar,然后定义了一个 Foo 类,在 Foo 类上改写了 Bar() 方法。