go之结构体

什么是结构体

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

语法

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

结构体定义

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

使用结构体

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

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 }
}

定义并初始化

  按位置初始化

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

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 男}
}

  按关键字初始化

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

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 男}
}

字段的取值赋值

  通过.

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
}

结构体零值

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

package main

import "fmt"

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

func main() {
	var p Person
	fmt.Println(p)  //{ 0 }
}

匿名结构体

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

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

func main() {
	a:= struct {
	age int
	name string
	}{19,"彭于晏"}
	fmt.Println(a.name)
	fmt.Println(a.age)
	fmt.Println(a)
}

结构体指针

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

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 字段。该程序会输出

First Name: Sam
Age: 55

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

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 字段,该程序会输出:

First Name: Sam
Age: 55

结构体当函数参数传递

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 男}

}

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

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 男}

}

匿名字段

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

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

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}
}

结构体嵌套

  结构体中套结构体

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自己的
}

导出结构体和字段

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包

package entity


type Person struct {  // 大写开头,外包才可以用
	Name string
	age int

}

结构体是值类型

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 @ 2022-09-19 11:27  那就凑个整吧  阅读(29)  评论(0编辑  收藏  举报