08-结构体(struct)

1. 定义结构体类型

  • 语法
type 结构体名称 struct {
   成员1  类型
   成员2  类型
   ...
}
  • 示例
type XiShu struct {
	ID int
	Name string
	Age int
	Position string
}

2. 声明结构体变量

  • 代码
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
}

func main() {
	var xiShu XiShu
	fmt.Printf("结构体为:%+v",xiShu)

}
  • 结果
结构体为:{ID:0 Name: Age:0}

示例可见:声明结构体变量之后,结构体不为空,结构体每个成员都为默认值(字串默认值为空,int 默认值为 0)。

3. 赋值

3.1 用结构体赋值

  • 语法
结构体名 =  结构体类型{ 成员1: 值1, 成员2: 值2,... }
  • 代码
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
}

func main() {
	xiShu := XiShu{
		ID: 1,
		Name: "刘备",
		Age: 28,
	}

	fmt.Printf("结构体为:%+v",xiShu)

}
  • 结果
结构体为:{ID:1 Name:刘备 Age:28}

3.2 每个成员分别赋值

  • 语法
结构体名.成员1 = 值
结构体名.成员2 = 值
  • 示例
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
}

func main() {
	var xiShu XiShu
    xiShu.Name = "刘备"
    xiShu.Age = 28

	fmt.Printf("结构体为:%+v",xiShu)

}

结果显示

结构体为:{ID:0 Name:刘备 Age:28}

4. 结构体使用

4.1 结构体作参数

  • 代码
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
}

//checkAge 定义函数,以结构体做参数。
func checkAge(info XiShu)(result string) {
	if info.Age >= 18 {
		result  = info.Name+"是一个成年人"
		return result
	}else {
		info.Name = "小"+info.Name
		result = info.Name+"还没有长大"
		return result
	}
}

func main () {
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
	}

	result := checkAge(liuBei)
	fmt.Println(result)
}
  • 结果输出
刘备是一个成年人

4.2 结构体指针做参数

  • 代码
  • 结构体指针可以直接使用,不需要多余操作。
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
}
//info 是一个结构体的指针
func checkAge(info *XiShu)(result string) {
	if info.Age >= 18 {
		result  = info.Name+"是一个成年人"
		return result
	}else {
		info.Name = "小"+info.Name
		result = info.Name+"还没有长大"
		return result
	}
}

func main () {
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
	}
     //将结构体liuBei的指针传入函数
	result := checkAge(&liuBei)
	fmt.Println(result)
}

4.3 二者区别

  • 结构体做参数,变化不会影响函数外
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
}

func IncreaseAge(info XiShu)(age int) {
        info.Age += 1
		fmt.Printf("函数中构体:\t%+v\n",info)
		age = info.Age
		return age
}

func main () {
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
	}
	fmt.Printf("原结构体:\t%+v\n",liuBei)
	IncreaseAge(liuBei)

	fmt.Printf("当前结构体:\t%+v\n",liuBei)
}

结果

原结构体:	{ID:0 Name:刘备 Age:28 Position:主公}
函数中构体:	{ID:0 Name:刘备 Age:29 Position:主公}
当前结构体:	{ID:0 Name:刘备 Age:28 Position:主公}

如上可见,结构体值变化不会影响函数外。

  • 结构体指针做参数,变化影响全局
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
}

func IncreaseAge(info *XiShu)(age int) {
        info.Age += 1
		fmt.Printf("函数中构体:\t%+v\n",info)
		age = info.Age
		return age
}

func main () {
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
	}
	fmt.Printf("原结构体:\t%+v\n",liuBei)
	IncreaseAge(&liuBei)

	fmt.Printf("当前结构体:\t%+v\n",liuBei)
}

结果:

原结构体:	{ID:0 Name:刘备 Age:28 Position:主公}
函数中构体:	&{ID:0 Name:刘备 Age:29 Position:主公}
当前结构体:	{ID:0 Name:刘备 Age:29 Position:主公}

如上可见,结构体数据彻底放生变化

4.4 本质原因

  • 说明:

函数中的形参和函数外的实参内存地址是不同的。
参数传递时,函数中的形参复制了函数外实参的值,函数结束后形参地址将被释放,这些不会对实参造成影响。

  • 示例

我们将实参的地址作为第二个参数传入函数,然后和第一个形参的地址做比较。

ackage main

import (
	"fmt"
)

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
}

func IncreaseAge(info XiShu,xiShu *XiShu) {
	fmt.Printf("比较形参和实参地址:")
     if &info == xiShu {
		 fmt.Println("相同")
	 }else {
		 fmt.Println("不同")
	}

}

func main () {
	//liuBei := new(XiShu)
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
	}
	IncreaseAge(liuBei,&liuBei)
}

结果:

比较形参和实参地址:不同

5. 结构体嵌套

5.1 一个结构体作为另一个结构体的成员

1)定义

  • 语法
type StructName02 struct {
	……
	MemberName StructName01
}
  • 语法示例
type XiShu struct {
	ID int
	Name string
	Age int
	Position string
	Equipment Equipment
}

type Equipment struct {
	Arms string
	Horse string
}

2)赋值和引用

  • 语法
StructName02.MemberName.StructName01Menber
  • 示例(用结构体赋值)

用结构体赋值只能使用StructName02.MemberName.StructName01Menber的方法

	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
		Equipment: Equipment{
			Arms: "双股剑",
			Horse: "的卢",
		},
	}
  • 示例(单个成员赋值)

单个赋值语法中两种方法都可以

	liuBei.Equipment.Arms = "双股剑"

3)完整示例

  • 代码
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
	Equipment Equipment
}

type Equipment struct {
	Arms string
	Horse string
}


func main () {
    //可以用结构体赋值
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
		Equipment: Equipment{
			Arms: "双股剑",
			//Horse: "的卢", //为了展示直接对成员赋值,此处先注释掉
		},
	}
	//也可以直接对成员赋值
	liuBei.Equipment.Horse = "的卢"
	fmt.Printf("%+v",liuBei)
}
  • 结果
{ID:0 Name:刘备 Age:28 Position:主公 Equipment:{Arms:双股剑 Horse:的卢}}

5.2 直接引入另一个结构体的所有成员

1)定义

  • 语法
type StructName02 struct {
	……
	StructName01
}
  • 语法示例
type XiShu struct {
	ID int
	Name string
	Age int
	Position string
	Equipment
}

type Equipment struct {
	Arms string
	Horse string
}

2)赋值和引用

  • 语法
StructName02.StructName01Menber

StructName02.MemberName.StructName01Menber
  • 示例(用结构体赋值)

用结构体赋值只能用StructName02.MemberName.StructName01Menber的结构,而不能使用StructName02.StructName01Menber的结构

	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
		Equipment: Equipment{
			Arms: "双股剑",
			Horse: "的卢",
		},
	}

如上,不能写成:

	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
		Arms: "双股剑", //不能这么写
		Horse: "的卢", //不能这么写
		},
	}
  • 示例(单个成员赋值)

StructName02.MemberName.StructName01Menber的结构和StructName02.StructName01Menber的结构都可以。

	liuBei.Arms = "双股剑"

	liuBei.Equipment.Arms = "双股剑"

3)完整示例

  • 代码
package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
	Equipment
}

type Equipment struct {
	Arms string
	Horse string
}


func main () {
	//用结构体赋值
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
		//Equipment: Equipment{  //为了展示单个成员赋值效果,此处可以注释掉
		//	Arms: "双股剑",
		//	Horse: "的卢",
		//},
	}
	//直接引用`Equipment`的成员
	liuBei.Arms = "双股剑"
	//通过Equipment引用其成员
	liuBei.Equipment.Horse = "的卢"

	fmt.Printf("%+v",liuBei)
}

  • 结果
{ID:0 Name:刘备 Age:28 Position:主公 Equipment:{Arms:双股剑 Horse:的卢}}

注意,虽然Equipment的成员可以直接引用,但是打印出的结果依然在Equipment下。

6. 结构体打印

6.1 仅打印值

  • 语法示例
fmt.Println(StructName)
  • 完整示例

代码:

package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
}

func main () {
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
	}
	
	fmt.Println(liuBei)
}

结果输出

{0 刘备 28 主公}

6.2 打印成员名和值

  • 语法示例
	fmt.Printf("%+v",StructName)
  • 完整示例

代码:

package main

import "fmt"

type XiShu struct {
	ID int
	Name string
	Age int
	Position string
}

func main () {
	liuBei := XiShu{
		ID: 0,
		Name: "刘备",
		Age: 28,
		Position: "主公",
	}
	
	fmt.Printf("%+v",liuBei)
}

结果输出

{ID:0 Name:刘备 Age:28 Position:主公}

posted on 2022-12-08 21:53  运维开发玄德公  阅读(15)  评论(0编辑  收藏  举报  来源

导航