玩转Go语言之结构体

295 阅读5分钟

结构体

//定义结构体类型
type Person struct {
   name string
   age int
   height float64
}

//定义结构体变量
var student Person

//给结构体属性赋值
student.name = "zhangsan"
student.age = 20
student.height = 170.0

//打印结构体
Println(student)

总结:

1.Go语言中的结构体几乎和C语言中的结构体一模一样

都需要先定义结构体类型, 再定义结构体变量
都是用来保存一组不同类型数据的

2.C语言定义结构体类型的格式

struct 结构体类型名称{
	    属性名称 属性类型;
	    属性名称 属性类型;
}

3.Go语言定义结构体类型的格式

typd 结构体类型名称 struct{
	    属性名称 属性类型;
	    属性名称 属性类型;
}

4.C语言中通过结构体类型定义结构体变量, 必须拷贝struct

struct 结构体类型名称 结构体变量名称;

5.Go语言中通过结构体类型定义结构体变量, 不用拷贝struct

var 结构体变量名称 结构体类型名称

6.和C语言中的结构体一样, 可以定义结构体变量的同时初始化, 也可以先定义结构体变量再初始化

注意点:

和切片以及字典不一样, 结构体变量定义之后就可以直接使用了

结构体与函数

//定义结构体类型
type Person struct {
   name string
}

func main()  {

   // 总结:结构体类型和数组一样都是值传递,修改形参的不会影响到实参

   //定义结构体变量
   var people Person

   //给结构体变量赋值
   people.name = "张三"

   //调用change函数
   change(people)

   //打印结构体
   Println(people)
}

func change(people Person)  {

   people.name = "李四"
}

结构体中含有切片,字典

func main() {
   type Person struct {
      age int
      score float32
      name string
      arr [3]int
      sce []int
      dict map[string]string
   }

   var per Person
   // 常规的数据类型, 我们都可以直接操作, 完全没有问题
   per.age = 18
   per.score = 100
   per.name = "lnj"
   per.arr[0] = 1
   per.arr[1] = 3
   per.arr[2] = 5
   fmt.Println(per)
   // 注意点: 如果结构体的属性是切片和字典类型, 那么就不能直接操作
   // 必须先给切片初始化(创建切片)
   per.sce = make([]int, 2)
   per.sce[0] = 123
   per.sce[1] = 456
   //per.sce[2] = 789 // 通过索引操作切片, 不能超出切片的长度
   fmt.Println(per)

   per.dict = make(map[string]string)
   per.dict["name"] = "zs"
   fmt.Println(per)
}

结构体类型之间转换

func main() {
   /*
   结构体变量之间可以相互转换, 但是必须保证结构体类型的
   属性名称 属性类型 属性顺序 属性的个数 都一样
    */

   type Person1 struct {
      name string
      age int
   }
   // 属性顺序不同
   type Person2 struct {
      age int
      name string
   }
   // 如果属性名称和类型都一样, 但是顺序不一样, 不能转换
   //var p1 Person1 = Person1{}
   //var p2 Person2
   //p2 = Person2(p1)
   //fmt.Println(p1)
   //fmt.Println(p2)

   type Person3 struct {
      name1 string
      age int
   }
   // 如果属性的类型和顺序都一样, 但是名称不一样, 不能转换
   //var p1 Person1 = Person1{}
   //var p2 Person3
   //p2 = Person3(p1)
   //fmt.Println(p1)
   //fmt.Println(p2)

   type Person4 struct {
      name string
      age int
      score int
   }
   // 如果属性的名称和类型都一样, 但是个数不一样, 不能转换
   //var p1 Person1 = Person1{}
   //var p2 Person4
   //p2 = Person4(p1)
   //fmt.Println(p1)
   //fmt.Println(p2)

   type Person5 struct {
      name [10]byte
      age int
   }
   // 如果属性名称和个数都一样, 但是属性数据类型不一样, 不能转换
   //var p1 Person1 = Person1{}
   //var p2 Person5
   //p2 = Person5(p1)
   //fmt.Println(p1)
   //fmt.Println(p2)

   type Person6 struct {
      name string
      age int
   }

   // 只有属性个数, 属性名称, 属性类型, 属性属性都一样, 才能转换
   var p1 Person1 = Person1{}
   var p2 Person6
   p2 = Person6(p1)
   fmt.Println(p1)
   fmt.Println(p2)
}

结构体匿名属性

func main() {
   /*
   1.什么是匿名结构体属性?
   没有名称的属性就是匿名属性

   2.如何操作匿名属性?
   匿名属性的数据类型就是匿名属性的名称, 所以可以通过匿名属性的数据类型来操作

   3.匿名属性一般都用于结构体的嵌套定义
   结构体的属性又是一个结构体
    */

   /*
   type Person struct {
      int // 只有数据类型, 没有名称, 就是匿名属性
      name string
   }

   //var per Person = Person{666, "lnj"}
   //fmt.Println(per)

   var per Person
   per.int = 666
   per.name = "lnj"
   fmt.Println(per)
   */

   type Date struct {
      year int
      month int
      day int
   }
   type Person struct {
      name string
      //year int
      //month int
      //day int
      Date
   }

   type Animal struct {
      name string
      //year int
      //month int
      //day int
      Date
   }

   //var per Person
   //per.name = "zs"
   //per.Date = Date{2012, 12,12}
   //fmt.Println(per) // {zs {2012 12 12}}

   var per Person = Person{"zs", Date{2012, 12, 12}}
   fmt.Println(per) // {zs {2012 12 12}}
}

结构体嵌套

func main() {
   /*
   第一种方式
   type 结构体名称1 struct{

   }
   type 结构体名称2 struct{
      结构体名称1
   }

   第二种方式
   type 结构体名称1 struct{

   }
   type 结构体名称2 struct{
      结构体名称1
   }
   type 结构体名称3 struct{
      结构体名称2
   }

   第三种方式
   type 结构体名称1 struct{

   }
   type 结构体名称2 struct{
   }
   type 结构体名称3 struct{
       结构体名称1
      结构体名称2
   }
    */

   // 第一种方式: 没有重名属性的情况
   /*
   type Person struct {
      name string
      age int
   }
   type Student struct {
      Person
      score float32
   }

   stu := Student{Person{"zs", 18}, 99.5}
   fmt.Println(stu)

   // 结构体嵌套定义时, 如果操作结构体的属性
   //fmt.Println(stu.Person.name)
   //fmt.Println(stu.Person.age)
   //fmt.Println(stu.score)

   // 第二种访问的方式
   // 会先去Student结构体中查询有没有name属性, 如果有就直接访问
   // 如果没有会继续查找嵌套的匿名结构体中有没有, 如果有就访问匿名结构体中的name属性
   //fmt.Println(stu.name)
   //fmt.Println(stu.age)
   //fmt.Println(stu.score)
   */

   // 第一种方式: 有重名属性的情况
   /*
   type Person struct {
      name string
      age int
   }
   type Teacher struct {
      Person
      name string
      title string
   }

   tea := Teacher{Person{"lnj", 33}, "zs", "老师"}
   fmt.Println(tea)
   fmt.Println(tea.name) // zs
   fmt.Println(tea.Person.name) // lnj
   */


   // 第二种方式: 没有重名属性的情况
   /*
   type Object struct {
      name string
   }
   type Person struct {
      Object
      age int
   }
   type Student struct {
      Person
      score float32
   }

   stu := Student{Person{Object{"zs"}, 18}, 99.5}
   fmt.Println(stu) // {{{zs} 18} 99.5}
   fmt.Println(stu.score)
   fmt.Println(stu.Person.age)
   fmt.Println(stu.age)
   fmt.Println(stu.Person.Object.name)
   fmt.Println(stu.Person.name)
   fmt.Println(stu.name)
   */

   // 第二种方式: 有重名属性的情况
   /*
   type Object struct {
      name string
   }
   type Person struct {
      Object
      name string
      age int
   }
   type Student struct {
      Person
      name string
      score float32
   }
   stu := Student{Person{Object{"lnj"}, "zs", 18}, "ww", 99.5}
   fmt.Println(stu)
   fmt.Println(stu.name) // ww
   fmt.Println(stu.Person.name) // zs
   fmt.Println(stu.Person.Object.name) // lnj
   */

   // 第三种方式: 没有重名属性的情况
   /*
   type Object struct {
      name string
   }
   type Person struct {
      age int
   }
   type Student struct {
      Object
      Person
      score float32
   }
   stu := Student{Object{"lnj"}, Person{18}, 99.5}
   fmt.Println(stu)
   fmt.Println(stu.Object.name)
   fmt.Println(stu.name)
   fmt.Println(stu.Person.age)
   fmt.Println(stu.age)
   */

   type Object struct {
      name string
   }
   type Person struct {
      name string
   }
   type Student struct {
      Object
      Person
      name string
      score float32
   }

   stu := Student{Object{"zs"}, Person{"ls"}, "lnj",99.5}
   fmt.Println(stu.name)
   fmt.Println(stu.Object.name)
   fmt.Println(stu.Person.name)
}