compose_test

  1. package main
  2. import "fmt"
  3. type Teacher struct {
  4. Name string
  5. Age int
  6. Title string
  7. }
  8. func (t Teacher) teacherInfo() {
  9. fmt.Printf("姓名:%s, 年龄:%d, 职称:%s", t.Name, t.Age, t.Title)
  10. }
  11. type Course struct {
  12. Teacher //如果讲师的信息比较多怎么办?将另一个结构体的变量放进来
  13. Name string
  14. Price int
  15. Url string
  16. }
  17. //匿名嵌套 这种做法其实就是我们的语法糖
  18. func (c Course) courseInfo() {
  19. fmt.Printf("课程名:%s, 价格:%d, 讲师信息:%s %d %s", c.Name, c.Price,
  20. c.Teacher.Name, c.Age, c.Title)
  21. }
  22. //这种继承的效果有点说服不了人
  23. func main() {
  24. //go语言的继承 组合
  25. t := Teacher{
  26. Name: "anwma",
  27. Age: 18,
  28. Title: "开发",
  29. }
  30. c := Course{
  31. Teacher: t,
  32. Price: 100,
  33. Url: "",
  34. Name: "django",
  35. }
  36. c.courseInfo()
  37. //c := Course{
  38. // Teacher: Teacher{
  39. // Name: "anwma",
  40. // Age: 18,
  41. // Title: "rd",
  42. // },
  43. //}
  44. }

new_pkg

  1. package new_pkg
  2. type Course struct {
  3. Name string
  4. Price int
  5. Url string
  6. }

struct_tag

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "reflect"
  6. )
  7. //type Info struct { //能表述的信息是有限的
  8. // // python中使用元类编程
  9. // Name string //name是映射成mysql中的char类型还是varchar类型还是text类型, 即使能够说明 但是额外的信息max_length
  10. // //Age int
  11. // //Age int `json:"age,omitempty"`
  12. // Age int //不加 默认值为0
  13. // Gender string
  14. //}
  15. // Info 结构体能基本上达到类的一个效果 多态
  16. type Info struct {
  17. Name string `orm:"name,max_length = 17,min_length = 5"`
  18. Age int `orm:"age,min = 18,max = 70"`
  19. Gender string `orm:"gender,required"`
  20. }
  21. //反射包
  22. func main() {
  23. //结构体标签
  24. /*
  25. 结构体的字段除了名字和类型外,还可以有一个可选的标签(tag):
  26. 它是一个附属于字段的字符串,可以是文档或其他的重要标记。
  27. 比如在我们解析json或生成json文件时,常用到encoding/json包,
  28. 它提供一些默认标签,例如:omitempty标签可以在序列化的时候忽略0值或者空值。
  29. 而-标签的作用是不进行序列化,其效果和和直接将结构体中的字段写成小写的效果一样。
  30. */
  31. info := Info{
  32. Name: "Wozen",
  33. //Age: 0,
  34. Gender: "男",
  35. }
  36. re, _ := json.Marshal(info)
  37. fmt.Println(string(re))
  38. //通过反射包去识别这些tag 简答的体验了一下反射的威力 spring 底层都是反射
  39. t := reflect.TypeOf(info)
  40. fmt.Println("Type:", t.Name())
  41. fmt.Println("Kind:", t.Kind())
  42. //Output:
  43. //Type: Info
  44. //Kind: struct
  45. for i := 0; i < t.NumField(); i++ {
  46. field := t.Field(i) //获取结构体的每一个字段
  47. tag := field.Tag.Get("orm")
  48. fmt.Printf("%d. %v (%v),tag: '%v'\n", i+1, field.Name, field.Type.Name(), tag)
  49. }
  50. //具体的应用绝大部分情况之下我们是不需要使用到反射的 实际开发的项目中会用到的
  51. }

struct_test

  1. package main
  2. import (
  3. "fmt"
  4. "unsafe"
  5. )
  6. type Course struct {
  7. Name string
  8. Price int
  9. Url string
  10. }
  11. // 结构体绑定方法 函数的接收者
  12. func (c Course) printCourseInfo() {
  13. fmt.Printf("课程名: %s, 课程价格: %d, 课程的地址: %s", c.Name, c.Price, c.Url)
  14. }
  15. func (c *Course) setPrice(price int) {
  16. c.Price = price
  17. }
  18. //结构体的方法只能和结构体在同一个包中
  19. //2.内置的int类型不能加方法
  20. func main() {
  21. //go语言不支持面向对象
  22. //面向对象的三个基本特征:封装 继承 多态 方法重载 抽象基类(不支持)
  23. //定义struct go语言没有class这个概念 所以说对于很多人来说会少理解很多面向对象抽象的概念
  24. //1.实例化 k-v方式
  25. //var c new_pkg.Course = new_pkg.Course{
  26. // Name: "django",
  27. // Price: 100,
  28. // Url: "https://www.imooc.com",
  29. //}
  30. //访问
  31. //fmt.Println(c.Name, c.Price, c.Url)
  32. //大小写在go语言中的重要性 可见性
  33. //一个包中的变量或者结构体如果首字母是小写,那么对于另一个包不可见
  34. //机构体定义的 名称 以及属性首字母大写很重要
  35. //2.第二种实例化方式 - 顺序形式
  36. //c2 := Course{"scrapy", 110, "https://www.imooc.com"}
  37. //fmt.Println(c2.Name, c2.Price, c2.Url)
  38. //3.如果一个指向结构体的指针 通过结构体指针获取对象的值
  39. //c3 := &Course{"tornado", 100, "https://www.imooc.com"}
  40. //fmt.Printf("%T\n", c3)
  41. //fmt.Println((*c3).Name, (*c3).Price, (*c3).Url)
  42. //fmt.Println("--------------")
  43. //应该能看出来 go语言实际上在借鉴很多动态语言的特性 -很多地方不管如何写都是正确的
  44. //另一个根本原因 go语言的指针是受限的
  45. //fmt.Println(c3.Name, c3.Price, c3.Url) //这里其实是go语言的一个语法糖 go语言内部会将c3转换为(*c3)
  46. //4.零值 如果不给结构体赋值 go语言会默认给每个字段采用默认值
  47. //c4 := Course{}
  48. //fmt.Println(c4.Name)
  49. //5.多种方式零值初始结构体
  50. //var c5 Course = Course{}
  51. //var c6 Course
  52. //var c7 *Course = new(Course)
  53. //var c8 *Course
  54. //var c9 *Course = &Course{}
  55. //为什么c6和c8表现出来的结果不一样 指针如果只声明不赋值 默认值是nil c6不是指针 是结构体的类型
  56. //fmt.Println("零值初始化")
  57. //fmt.Println(c5.Price)
  58. //fmt.Println(c6.Price)
  59. //fmt.Println(c7.Price)
  60. //fmt.Println(c8.Price)
  61. //fmt.Println(c9.Price)
  62. //6.结构体是值类型
  63. c10 := Course{"scrapy", 110, "https://www.imooc.com"}
  64. c11 := c10
  65. fmt.Println(c10)
  66. fmt.Println(c11)
  67. c10.Price = 200
  68. fmt.Println(c10)
  69. fmt.Println(c11)
  70. //go语言中struct无处不在
  71. //7.结构体的大小 占用内存的大小 可以使用sizeof来查看对象占用的类型
  72. fmt.Println(unsafe.Sizeof(1)) //8
  73. //go语言string的本质 其实string是一个结构体 16个字节
  74. //type string struct {
  75. // Data uintptr //指针占8个长度
  76. // Len int //长度64位系统占8个长度
  77. //}
  78. fmt.Println(unsafe.Sizeof("scrapy")) //16
  79. fmt.Println(unsafe.Sizeof(c10)) //16
  80. //8.slice的大小 24个字节
  81. type slice struct {
  82. array unsafe.Pointer //底层数组地址
  83. len int //长度
  84. cap int //容量
  85. }
  86. s1 := []int{1, 2, 4, 5}
  87. s2 := []string{"hello"}
  88. fmt.Println("切片的大小:")
  89. fmt.Println(unsafe.Sizeof(s1))
  90. fmt.Println(unsafe.Sizeof(s2))
  91. m1 := map[string]string{
  92. "hello1": "world1",
  93. "hello2": "world2",
  94. "hello3": "world3",
  95. }
  96. fmt.Println(unsafe.Sizeof(m1)) //8
  97. //结构体方法 达到了封装数据和封装方法的效果
  98. c10 = Course{"scrapy", 100, "https://www.imooc.com"}
  99. //Course.printCourseInfo(c10)
  100. //Course.setPrice(c10, 200)
  101. (&c10).setPrice(200) //修改c10的price?为什么呢? 内部转换 语法糖 函数参数的传递是怎么传递的 结构体是值传递
  102. fmt.Println(c10.Price)
  103. //c10.printCourseInfo()
  104. //结构体的接收者有两种形式 1.值传递2.指针传递 如果你想改结构体的值 如果结构体的数据很大
  105. //go语言不支持继承 但是有办法能达到同样的效果 组合
  106. }

type_test

  1. package main
  2. import "fmt"
  3. func main() {
  4. //go语言中的关键词 type
  5. //1.给一个类型定义别名,实际上为什么会有byte 就是我为了强调我们现在处理的对象是字节类型
  6. //2.这种别名实际上还是为了代码的可读性,这个实质上本质仍然是uint8 无非就是在代码编码阶段可读性强而已
  7. //rune byte
  8. type myByte = byte
  9. var b myByte
  10. fmt.Printf("%T\n", b)
  11. //3.第二种就是基于一个已有的类型定义一个新的类型
  12. type myInt int
  13. var i myInt
  14. fmt.Printf("%T\n", i)
  15. //4.定义结构体
  16. type Course struct {
  17. name string
  18. price int
  19. }
  20. //5.定义接口、
  21. type Callable interface {
  22. }
  23. //6.定义函数别名
  24. type handle func(str string)
  25. }