天天看点

Go语言学习、结构体

最近疫情比较严重,过年也不能出门,闲来无事,继续更新博客吧。

武汉加油!

我们来继续说下go语言中的结构体

比如我们现在想存储一个学生信息,如:学号、姓名、年龄、性别,等信息,按照我们以前的存储习惯,将分别定义各个类型的字段,来表示不同的字段,不同的数据类型。

通过以往的定义形式进行存储,这种方法可行,但是相对来说,比较麻烦,且不利于数据的管理。

但是在GO语言中,我们可以通过结构体的形式来存储数据,下面我们看下,结构体的定义:

package main

import "fmt"

//在函数外部定义结构体,作用全局。
//结构体定义
//type 名称 struct {
//结构体成员列表
//}
type Student struct {
	id int
	name string
	sex string
	age int
	addr string
}


func main() {
	//通过结构体名, 定义结构体变量
	var stdu Student
	//结构体变量名.成员名称
	stdu.id = 111
	stdu.name = "张三"
	stdu.sex = "男"
	stdu.age = 26
	stdu.addr = "成都"

	fmt.Println(stdu)
}
           

输出结果:

{111 张三 男 26 成都}
           

另外一种定义方式:

在写结构体参数时,固定按照定义的结构体顺序来写

func main() {
	var stdu Student=Student{111,"张三", "男", 28, "成都"}
	fmt.Println(stdu)
}
           

我们在看看自动推导类型如何定义结构体

stdu_1:= Student{age:26, id:222, name:"李四", addr:"成都", sex:"男"}
           

我们在使用自动推导类型定义结构体的时候,需要将结构体中的参数添加在定义变量之前。

二、结构体的赋值和比较

package main

import "fmt"

type Student struct {
	id   int
	name string
	sex  string
	age  int
	addr string
}

func main() {
	s:= Student{1, "啦啦", "男", 18, "成都"}
	//结构体变量赋值
	s1:=s
	fmt.Println(s1)
	//改变结构体中的值
	s1.age=26
	fmt.Println(s1)
	//我们看看,修改的值,会不会影响我们原来的s
	fmt.Println(s)
}
           

结果:

{1 啦啦 男 18 成都}
{1 啦啦 男 26 成都}
{1 啦啦 男 18 成都}
           

我们可以看到,我们将结构体s赋值给s1打印,s1,得到跟s结构体一样的信息

在将,s1的年龄更改至26岁,打印s1, 打印s,可以看到,修改s1的值,不会更改s的值.。

结构体比较

//在结构体中,比较操作,使用“==”或者“!=”来比较,不能大于小于等。
	if s1!=s{
		fmt.Println("不相同")
	}else {
		fmt.Println("相同")
	}
           

结果:

不相同
           

在结构体中,只能使用“==”或“!=”进行比较,不可以使用大于、小于等作为结构体的比较。

大于小于,可以用于对结构体成员进行比较。

if s.age>s1.age{
		fmt.Println("s的年龄,大于s1的年龄")
	}else {
		fmt.Println("s的年龄,小于s1的年龄")
	}
           

结果:

s的年龄,小于s1的年龄
           

三、结构体数组切片的定义于使用

前面我们已经对结构体的定义,与基本使用做了一定的介绍。

1、结构体数组

package main

import "fmt"

type student struct {
	id    int
	name  string
	sex   string
	age   int
	score int
	addr  string
}

func main() {
	//var 结构体变量名 结构体类型
	//定义结构体数组
	//var 结构体数组名[元素个数] 结构体类型
	var arr[5]student
	// len(数组名)计算数组元素个数
	//fmt.Println(len(arr))
	for i:=0; i<len(arr) ;i++{
		fmt.Scan(&arr[i].id,&arr[i].name,&arr[i].sex,&arr[i].age,&arr[i].score,&arr[i].addr)

	}
	fmt.Println(arr)
}
           

结果:

1 哈哈 男 18 88 成都
2 啦啦 女 16 99 北京
3 呆呆 男 17 77 上海
4 哒哒 女 15 66 广州
5 嘎嘎 男 14 55 深圳
[{1 哈哈 男 18 88 成都} {2 啦啦 女 16 99 北京} {3 呆呆 男 17 77 上海} {4 哒哒 女 15 66 广州} {5 嘎嘎 男 14 55 深圳}]
           

输入上面的数据,打印结构体数组得到的内容。

通过循环方式,输出结构体数据内容

//fmt.Println(arr)
	//通过循环方式,将结构体的每一项输出
	for i:=0; i<len(arr); i++ {
		fmt.Println(arr[i])
	}
           

结果:

1 哈哈 男 18 88 成都
2 啦啦 女 16 99 北京
3 呆呆 男 17 77 上海
4 哒哒 女 15 66 广州
5 嘎嘎 男 14 55 深圳
{1 哈哈 男 18 88 成都}
{2 啦啦 女 16 99 北京}
{3 呆呆 男 17 77 上海}
{4 哒哒 女 15 66 广州}
{5 嘎嘎 男 14 55 深圳}
           

2、根据结构体成员信息进行排序操作(冒泡排序算法)

package main

import "fmt"

type student struct {
	id    int
	name  string
	sex   string
	age   int
	score int
	addr  string
}

func main() {
	//var 结构体变量名 结构体类型
	//定义结构体数组
	//var 结构体数组名[元素个数] 结构体类型
	var arr[5]student
	// len(数组名)计算数组元素个数
	//fmt.Println(len(arr))
	for i:=0; i<len(arr) ;i++{
		fmt.Scan(&arr[i].id,&arr[i].name,&arr[i].sex,&arr[i].age,&arr[i].score,&arr[i].addr)

	}
	//fmt.Println(arr)
	//通过循环方式,将结构体的每一项输出
	fmt.Println("排序前:")

	for i:=0; i<len(arr); i++ {
		fmt.Println(arr[i])
	}

	//根据结构体成员信息进行排序操作,使用冒泡排序算法
	for i:=0; i< len(arr)-1; i++{
		for j:=0;j<len(arr)-1-i;j++{
			//比较结构体成员信息,年龄,成绩均可以进行排序
			if arr[j].age>arr[j+1].age{
				//通过比较交换成员
				arr[j],arr[j+1]=arr[j+1],arr[j]
			}

		}
	}
	fmt.Println("排序后:")
	for i:=0; i<len(arr); i++ {
		fmt.Println(arr[i])
	}
}
           

结果:

1 哈哈 男 18 88 成都
2 啦啦 女 16 99 北京
3 呆呆 男 17 77 上海
4 哒哒 女 15 66 广州
5 嘎嘎 男 14 55 深圳
排序前:
{1 哈哈 男 18 88 成都}
{2 啦啦 女 16 99 北京}
{3 呆呆 男 17 77 上海}
{4 哒哒 女 15 66 广州}
{5 嘎嘎 男 14 55 深圳}
排序后:
{5 嘎嘎 男 14 55 深圳}
{4 哒哒 女 15 66 广州}
{2 啦啦 女 16 99 北京}
{3 呆呆 男 17 77 上海}
{1 哈哈 男 18 88 成都}
           

数组中的元素,允许相互赋值操作,将结构体成员中的所有数据进行相互交换。

3、使用自动类型推导,创建结构体

package main

import "fmt"

type students struct {
	id    int
	name  string
	sex   string
	age   int
	score int
	addr  string
}


func main() {
	//使用自动类型推导创建结构体信息
	arr:=[3]students{
		{101,"啦啦","男", 50, 99,"成都"},
		{102,"哈哈","女",40,100,"北京"},
		{103,"嘎嘎", "男",30,88,"上海"},
	}

	for i,v:=range arr{
		//打印类型
		//fmt.Printf("%T",v)
		fmt.Println(i,v)
	}
}
           

结果:

0 {101 啦啦 男 50 99 成都}
1 {102 哈哈 女 40 100 北京}
2 {103 嘎嘎 男 30 88 上海}
           

4、切片结构体定义:

区别:[元素个数] 数组      []切片

arr:=[]students{
		{101,"啦啦","男", 50, 99,"成都"},
		{102,"哈哈","女",40,100,"北京"},
		{103,"嘎嘎", "男",30,88,"上海"},
	}
           

一样可以进行打印运行。

package main

import "fmt"

type students struct {
	id    int
	name  string
	sex   string
	age   int
	score int
	addr  string
}


func main() {
	//使用自动类型推导创建结构体信息
	// [元素个数] 数组    [] 切片
	arr:=[]students{
		{101,"啦啦","男", 50, 99,"成都"},
		{102,"哈哈","女",40,100,"北京"},
		{103,"嘎嘎", "男",30,88,"上海"},
	}

	//在切片中添加数据信息
	arr = append(arr,students{104,"哒哒", "男",40,77,"广州"})
	for i,v:=range arr{
		//打印类型
		//fmt.Printf("%T",v)
		fmt.Println(i,v)

	}
}
           

结果:

0 {101 啦啦 男 50 99 成都}
1 {102 哈哈 女 40 100 北京}
2 {103 嘎嘎 男 30 88 上海}
3 {104 哒哒 男 40 77 广州}
           

四、结构体作为Map中的值

package main

import "fmt"

type stu struct {
	name  string
	age   int
	score int
}

func main() {
	//定义一个map
	m:=make(map[int]stu)
	m[1] = stu{"哈哈", 50,88}
	m[2] = stu{"哒哒",51,88}
	fmt.Println(m)
}
           

结果:

map[1:{哈哈 50 88} 2:{哒哒 51 88}]
           

使用循环遍历map中的值

for k,v:=range m{
		fmt.Println(k,v)
	}
           

结果:

1 {哈哈 50 88}
2 {哒哒 51 88}
           

五、结构体切片作为map中的值

package main

import "fmt"

type stu struct {
	name  string
	age   int
	score int
}

func main()  {
	//结构体切片作为map中的值
	m:=make(map[int][]stu)
	// map结构体切片赋值
	m[1] = append(m[1],stu{"哈哈1",51,81},
					   stu{"哒哒1",61,91})
	m[2] = append(m[2],stu{"哈哈2",52,82},
	                   stu{"哒哒2",62,82})
	m[3] = append(m[3],stu{"哈哈3",53,83},
				   	   stu{"哒哒3",63,93})

	//遍历操作
	for k,v:=range m{
		//此时,V的类型为,结构体切片。
		//在遍历切片信息
		for i,data:=range v{
			fmt.Println("key:",k,"index:",i,"value:",data)
		}
	}
}
           

结果:

key: 1 index: 0 value: {哈哈1 51 81}
key: 1 index: 1 value: {哒哒1 61 91}
key: 2 index: 0 value: {哈哈2 52 82}
key: 2 index: 1 value: {哒哒2 62 82}
key: 3 index: 0 value: {哈哈3 53 83}
key: 3 index: 1 value: {哒哒3 63 93}
           

六、结构体作为函数参数

package main

import "fmt"

type person struct {
	id int
	name string
	score int
	sex string
}

func test(s person){
	fmt.Println(s.name)
	fmt.Println(s.score)
	fmt.Println(s.sex)
}


func main() {
	stu:=person{1,"哈哈", 55,"男"}
	//结构体作为函数参数
	test(stu)
}
           

结果:

哈哈
55
男
           

结构体作为函数参数是值传递

package main

import "fmt"

type person struct {
	id int
	name string
	score int
	sex string
}

func test(s person){
	s.name = "哒哒哒"
}


func main() {
	stu:=person{1,"哈哈", 55,"男"}
	//结构体作为函数参数
	test(stu)
	//结构体作为函数参数,是值传递。
	fmt.Println(stu)
}
           

结果:没有改变结构体名称,值传递。

值传递,形参单元和实参单元是不同的存储区域,修改不会影响其他的值。(这里注意,所有的切片类型,都为地址传递)

{1 哈哈 55 男}
           

结构体切片,作为参数地址传递。

package main

import "fmt"

type person struct {
	id int
	name string
	score int
	sex string
}

//所有的切片,都是地址传递
func test(stu []person){
	stu[0].name = "哒哒"
}


func main() {
	//定义结构体切片
	stu:=[]person{{1,"哈哈", 55,"男"},
				  {2,"啦啦", 88,"女"}}
	//为切片添加数据
	stu = append(stu,person{3,"嘎嘎",66,"男"})
	//结构体切片作为函数参数是地址传递
	//结构体数组作为函数参数是值传递
	test(stu)
	fmt.Println(stu)
}
           

结果:

[{1 哒哒 55 男} {2 啦啦 88 女} {3 嘎嘎 66 男}]