Go语言-结构体(go语言结构体赋值)

在 Go 语言中,结构体(struct) 是一种用户自定义的聚合数据类型,它可以将多个不同类型的字段组合在一起,形成一个整体。结构体类似于其他编程语言中的“类”或“记录”,但 Go 语言本身不支持类和继承,而是通过结构体和接口来实现面向对象编程的特性。


1. 定义结构体

使用 type 关键字定义结构体,并使用 struct 关键字表示结构体类型。例如:

package main

import "fmt"

// 定义一个结构体
type Person struct {
    Name string
    Age  int
}

func main() {
    // 创建结构体实例
    p := Person{"张三", 25}
    fmt.Println(p) // 输出: {张三 25}
}

2. 结构体字段访问和修改

可以使用 点号(.) 访问和修改结构体的字段:

p := Person{"李四", 30}
fmt.Println(p.Name) // 访问字段
p.Age = 35          // 修改字段
fmt.Println(p.Age)  // 输出: 35

3. 结构体实例化的方式

3.1 直接赋值

p1 := Person{"王五", 40}

3.2 指定字段名称

p2 := Person{Name: "赵六", Age: 28}

3.3 使用new

p3 := new(Person)  // 返回的是指针 *Person
p3.Name = "小明"
p3.Age = 22
fmt.Println(*p3)  // 输出: {小明 22}

3.4 取地址符&

p4 := &Person{"小红", 18}
fmt.Println(p4.Name) // Go 自动解引用

4. 结构体方法

结构体可以定义方法,方法的接收者可以是 值类型指针类型

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// 方法(值类型接收者)
func (p Person) SayHello() {
    fmt.Println("Hello, 我是", p.Name)
}

// 方法(指针类型接收者,修改值)
func (p *Person) GrowUp() {
    p.Age += 1
}

func main() {
    p := Person{"小明", 20}
    p.SayHello() // 输出: Hello, 我是 小明

    p.GrowUp()
    fmt.Println(p.Age) // 输出: 21
}

注意:

  • 如果方法的接收者是值类型 func (p Person) Method(),它不会修改原始结构体。
  • 如果方法的接收者是指针 func (p *Person) Method(),它可以修改原始结构体。

5. 结构体嵌套和继承(模拟继承)

Go 语言没有类和继承,但可以通过结构体嵌套来实现类似继承的功能:

type Animal struct {
    Name string
}

func (a Animal) Speak() {
    fmt.Println(a.Name, "会叫")
}

type Dog struct {
    Animal // 结构体嵌套
    Breed  string
}

func main() {
    d := Dog{Animal{"小狗"}, "哈士奇"}
    d.Speak() // 小狗 会叫
    fmt.Println(d.Breed) // 哈士奇
}

这里 Dog 继承了 Animal 的 Speak 方法。


6. 结构体与json互转

结构体可以与 JSON 相互转换:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    // 结构体转 JSON
    p := Person{"小李", 26}
    jsonData, _ := json.Marshal(p)
    fmt.Println(string(jsonData)) // 输出: {"name":"小李","age":26}

    // JSON 转结构体
    jsonString := `{"name":"小王","age":30}`
    var p2 Person
    json.Unmarshal([]byte(jsonString), &p2)
    fmt.Println(p2) // 输出: {小王 30}
}

注意:

  • 通过 json:"name" 指定 JSON 字段名,防止 Go 结构体字段大小写问题。

7. 结构体标签(Tag)

结构体的字段可以带 Tag,用于 JSON、数据库等格式转换:

type User struct {
    ID    int    `json:"id" db:"user_id"`
    Name  string `json:"name" db:"username"`
}
  • json:"id" 用于 JSON 序列化时字段名称。
  • db:"user_id" 用于数据库 ORM 访问时的字段名称。

8. 结构体比较

Go 语言的结构体可以直接使用 == 或 != 进行比较(但结构体不能包含不可比较的字段,如 map 或 slice):

type Point struct {
    X, Y int
}

p1 := Point{1, 2}
p2 := Point{1, 2}
fmt.Println(p1 == p2) // 输出: true

9. 结构体作为函数参数

结构体可以作为函数参数,通常有两种方式:

9.1 传值(不会影响原结构体)

func PrintPerson(p Person) {
    fmt.Println(p.Name, p.Age)
}

调用时:

PrintPerson(p) // 传递的是副本

9.2 传指针(可以修改原结构体)

func UpdateAge(p *Person) {
    p.Age += 1
}

调用时:

UpdateAge(&p) // 传递的是地址

10. 结构体内存对齐

Go 语言的结构体在内存中会进行 内存对齐,优化性能。一般来说:

  • 较大的字段应放前面,减少内存浪费
  • 使用 unsafe.Sizeof() 查看结构体大小:
import "unsafe"
fmt.Println(unsafe.Sizeof(Person{})) // 输出结构体所占字节数

总结

结构体特性

说明

定义结构体

type StructName struct {}

访问字段

使用 . 访问字段

结构体方法

使用 (s Struct) Method() 或 (*s Struct) Method()

结构体嵌套

通过嵌套结构体实现类似继承

结构体与 JSON

json.Marshal() / json.Unmarshal()

结构体标签

json:"name" / db:"column_name"

结构体比较

== / !=(不可包含 map/slice)

结构体传参

传值(副本) / 传指针(修改原结构体)

结构体是 Go 语言中非常重要的特性,它提供了类似面向对象编程的功能,但同时保持了 Go 语言的简洁性和高效性。

原文链接:,转发请注明来源!