GO语言入门指南:Go初始化Struct | 青训营

59 阅读5分钟

面向对象编程语言最基础的概念就是类(class),不过Go语言并没有类的概念,所以使用Go语言开发时,我们一般会用struct(结构体)来模拟面向对象中的类。

类一般是通过构造方法(constructors)来初始化类的实例(对象)中的属性,不过Gostruct并没有构造方法这种机制,那要怎么样初始化struct类型的实例呢?

下面我们来介绍几种创建struct类型变量的方法。

结构体字面量

使用结构体字面量:可以直接给结构体的字段指定初始值。示例如下:

type Person struct {
    Name   string
    Age    int
    Gender string
}

func main() {
    p := Person{
        Name:   "Alice",
        Age:    25,
        Gender: "female",
    }
    
    fmt.Printf("Name: %s, Age: %d, Gender: %s\n", p.Name, p.Age, p.Gender)
}

输出结果:

Name: Alice, Age: 25, Gender: female

使用 new 关键字

使用 new 关键字:可以使用 new 函数创建一个指向结构体的指针,并返回该指针的地址。示例如下:

type Person struct {
    Name   string
    Age    int
    Gender string
}

func main() {
    p := new(Person)
    p.Name = "Alice"
    p.Age = 25
    p.Gender = "female"
    
    fmt.Printf("Name: %s, Age: %d, Gender: %s\n", p.Name, p.Age, p.Gender)
}

输出结果与上述方式相同:

Name: Alice, Age: 25, Gender: female

构造函数

前面我们说过Go语言的struct没有构造函数,但是我们可以自定义函数来初始化struct,自定义函数的好处在于:

  • 可以达到复用的目的。
  • 可以起到封装的效果。
  • 可以校验初始化值是否在允许的范围内。

在 Go 语言中,没有像其他语言那样提供直接的构造函数的概念。但是我们可以使用一些约定和技巧来模拟构造函数的功能。

一种常见的约定是通过定义一个以 New 开头的函数来创建结构体的实例,并对其进行初始化。这个函数可以返回该结构体的指针,以提供对新创建的实例的访问。示例如下:

type Person struct {
    Name   string
    Age    int
    Gender string
}

func NewPerson(name string, age int, gender string) *Person {
    return &Person{
        Name:   name,
        Age:    age,
        Gender: gender,
    }
}

func main() {
    p := NewPerson("Alice", 25, "female")
    
    fmt.Printf("Name: %s, Age: %d, Gender: %s\n", p.Name, p.Age, p.Gender)
}

输出结果与之前的示例相同:

Name: Alice, Age: 25, Gender: female

在 NewPerson 函数内部,我们可以进行任何需要的初始化操作,并返回创建的结构体实例的指针。这种方式可以让我们在创建实例时,保持一致的初始化方法,并提供更好的可读性和可维护性。

支持可变参数的构造函数

在 Go 语言中,我们可以使用可变参数来定义构造函数,使其能够接受不定数量的参数。

下面是一个示例,在构造函数中使用可变参数来初始化结构体实例:

type Person struct {
    Name   string
    Age    int
    Gender string
}

func NewPerson(name string, age int, gender string, hobbies ...string) *Person {
    p := &Person{
        Name:   name,
        Age:    age,
        Gender: gender,
    }
    
    for _, hobby := range hobbies {
        p.Hobbies = append(p.Hobbies, hobby)
    }
    
    return p
}

func main() {
    p := NewPerson("Alice", 25, "female", "reading", "traveling", "cooking")
    
    fmt.Printf("Name: %s, Age: %d, Gender: %s\n", p.Name, p.Age, p.Gender)
    fmt.Println("Hobbies:", p.Hobbies)
}

输出结果:

Name: Alice, Age: 25, Gender: female
Hobbies: [reading traveling cooking]

在 NewPerson 函数中,我们可以看到最后一个参数 hobbies ...string 使用了可变参数语法。它允许我们传递任意数量的字符串参数。

在函数体内,我们首先创建一个 Person 结构体实例,并初始化其基本字段。然后使用 ... 语法将可变参数 hobbies 展开为一个字符串切片,并逐个添加到结构体实例的 Hobbies 字段中。

这样,我们就实现了一个能够接受可变数量参数的构造函数,并完成了结构体实例的初始化。

对go语言中Struct的一些思考

在 Go 语言中,struct 是一种用于组织和存储多个字段的数据类型。它类似于其他编程语言中的结构体或类,但具有一些独特的特性和设计原则。

使用 struct 可以将相关的字段组织到一起,并形成一个独立的实体。这样可以增加代码的可读性和可维护性,因为相关字段被聚合到了一个结构体中,方便了对相关数据的访问和操作。

struct 在 Go 语言中还常用于定义自定义的数据类型,可以根据具体需求来定义不同的结构体。每个结构体可以具有自己的字段,并且这些字段可以包括不同的数据类型,例如基本类型(如整数和字符串),以及其他结构体类型和接口类型。

Go 语言的 struct 还支持面向对象的特性,例如方法(在结构体上定义的函数)和封装(通过访问控制来限制字段和方法的可见性)。这使得 struct 可以充当面向对象编程的基础组件,用于实现封装、继承和多态等概念。

另外,Go 语言的 struct 还可以使用标签(tag)来为字段附加元数据。这些标签可以用于实现序列化、反序列化、数据验证等功能。标签可以在运行时使用反射来访问和解析。

总的来说,Go 语言中的 struct 提供了一种灵活而强大的机制,用于定义和组织数据结构,并支持面向对象的特性。使用 struct 可以使代码更具有组织性、可读性和可维护性,同时也提供了很多扩展性和灵活性的设计选项。