go之结构体

什么是结构体

  结构体是用户定义的类型,表示若干个字段的集合,有时应该把数据整合一起,而不是让这些数据没有联系,这种情况下可以使用结构体

语法

1
2
3
4
5
// 结构体
//type关键字  结构体名字  struct{
// 字段1 字段类型
// 字段2 字段类型
//}

结构体定义

1
2
3
4
5
type Person struct // 如果小写,在其他包使用不到Person结构体
    Name string  // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age uint8
    Sex string
}

使用结构体

  结构体是值类型,有默认零值,如果当函数参数传递,在函数中修改,不会影响原来的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main
 
import "fmt"
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    var p Person       // 没有初始化,有零值,零值是每个字段的零值
    fmt.Println(p.age) //0  有默认零值,字段的零值
    fmt.Println(p)     //{ 0 }
}

定义并初始化

  按位置初始化

  按照顺序,有几个字段,必须传几个字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
 
import "fmt"
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    var p Person=Person{"zys",18,"男"}
    fmt.Println(p)  //{zys 18 男}
}

  按关键字初始化

  不用按顺序,字段不用都传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
 
import "fmt"
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    var p Person=Person{Sex:"男",age:19}
    fmt.Println(p)  //{ 19 男}
}

字段的取值赋值

  通过.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
 
import "fmt"
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    var p Person=Person{Sex:"男",age:19}
    fmt.Println(p)  //{ 19 男}
    fmt.Println(p.Name)
    p.Name="xx"
    fmt.Println(p.Name)  //xx
}

结构体零值

  不初始化有默认零值,零值是各个字段的零值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
 
import "fmt"
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    var p Person
    fmt.Println(p)  //{ 0 }
}

匿名结构体

  结构体没有名字和type关键字,一般定义在函数内部,只使用一次

  好处是:多个变量可以包装到一个变量中

1
2
3
4
5
6
7
8
9
func main() {
    a:= struct {
    age int
    name string
    }{19,"彭于晏"}
    fmt.Println(a.name)
    fmt.Println(a.age)
    fmt.Println(a)
}

结构体指针

  还可以创建只想结构体的指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
 
import
    "fmt"
)
 
type Employee struct
    firstName, lastName string
    age, salary         int
}
 
func main() { 
    emp8 := &Employee{"Sam", "Anderson", 55, 6000}
    fmt.Println("First Name:", (*emp8).firstName)
    fmt.Println("Age:", (*emp8).age)
}

  在上面程序中,emp8 是一个指向结构体 Employee 的指针。(*emp8).firstName 表示访问结构体 emp8 的 firstName 字段。该程序会输出

1
2
First Name: Sam
Age: 55

  Go 语言允许我们在访问 firstName 字段时,可以使用 emp8.firstName 来代替显式的解引用 (*emp8).firstName

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main
 
import
    "fmt"
)
 
type Employee struct
    firstName, lastName string
    age, salary         int
}
 
func main() { 
    emp8 := &Employee{"Sam", "Anderson", 55, 6000}
    fmt.Println("First Name:", emp8.firstName)
    fmt.Println("Age:", emp8.age)
}

  在上面的程序中,我们使用 emp8.firstName 来访问 firstName 字段,该程序会输出:

1
2
First Name: Sam
Age: 55

结构体当函数参数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
 
import "fmt"
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    var p =Person{"zys",18,"男"}
    test5(p)
    fmt.Println("----",p)  // p 不受影响  ---- {zys 18 男}
}
func test5(p Person)  {
    fmt.Println(p)  //{zys 18 男}
    p.Name="lyf"
    fmt.Println(p)  //{lyf 18 男}
 
}

结构体指针当函数参数传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
 
import "fmt"
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    var p = &Person{"zys", 18, "男"}
    test6(p)               //指针传入,地址copy传入,改了就影响原来
    fmt.Println("----", p) // p 受影响  ---- &{lyf 18 男}
}
func test6(p *Person) {
    fmt.Println(p) //&{zys 18 男}
    p.Name = "lyf"
    //(*p).Name="lyf"
    fmt.Println(p) //&{lyf 18 男}
 
}

匿名字段

  字段没有名字,跟结构体是否匿名没有必然联系

  作用:可以做字段提升,实现面向对象的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
 
import "fmt"
 
type Animal struct {
    string // 字段没有名字,但是不能出现两个同种类型的字段 ,字段名就是类型名
    int
}
 
func main() {
    //var a =Animal{"小鸭子",1}
    var a = Animal{string: "小鸭子", int: 1}
    fmt.Println(a) //{小鸭子 1}
}

结构体嵌套

  结构体中套结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main
 
import "fmt"
 
func main() {
    type Animal struct {
        Name string
        age  int
    }
    type Dog struct {
        //Name string
        //age int
        // 简写成--->结构体嵌套
        //animal Animal
        Animal //匿名字段,Animal字段匿名了,字段名就是类型名,而且不用写name和age了
        //Dog比Animal多的字段
        Speak bool
    }
    //var dog =Dog{Animal{"二哈",3},true}
    var dog = Dog{Animal: Animal{"二哈", 3}, Speak: true}
    //面向对象继承,1 少写代码  2 子类对象.属性 如果子类没有,直接使用父类的
    fmt.Println(dog.Name) //二哈  dog的name本来是Animal的,使用了匿名字段,字段提升了
    //如果Animal不是匿名字段,不能提升
    fmt.Println(dog.Animal.Name) //二哈  指名道姓用   dog.Animal 相当于 super()
    //Dog中有Name,Animal 用了匿名字段,Name冲突了,会优先使用Dog自己的
}

导出结构体和字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
 
import (
    "day01/entity"
    "fmt"
)
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    //var p =entity.Person{"lyf",37}  // age 小写,外包包不能用
    var p =entity.Person{Name:"lyf"}
    fmt.Println(p)  //{lyf 0}
}

  entity包

1
2
3
4
5
6
7
8
package entity
 
 
type Person struct // 大写开头,外包才可以用
    Name string
    age int
 
}

结构体是值类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main
 
import (
    "fmt"
)
 
type Person struct { // 如果小写,在其他包使用不到Person结构体
    Name string // 字段大写,表示导出,如果小写,表示隐藏,在其他包中取不到
    age  uint8
    Sex  string
}
 
func main() {
    //如果它的每一个字段都是可比较的,则该结构体也是可比较的。
    //如果两个结构体变量的对应字段相等,则这两个变量也是相等的
    var p1=Person{"zys",19,"男"}
    var p2=Person{Name: "zys",age: 19,Sex: "男"}
    p2.age=20
    if p1==p2{
        fmt.Println("p1 和p2 相等")
    }else{
        fmt.Println(1)  //1
    }
 
    //如果结构体包含不可比较的字段(有引用类型),则结构体变量也不可比较
    //type Cat struct {
    //Name string
    //age int
    //wife []string  // 可以有很多异性猫
    //}
    //var c1 =Cat{"小野豹",3,[]string{"女朋友1号","女朋友2号"}}
    //var c2 =Cat{"小野豹",3,[]string{"女朋友1号","女朋友2号"}}
    //if c1==c2{
    //
    //}
}

  

posted @   那就凑个整吧  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示