暫無描述

chapter1-why-generics.slide 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. # Go 泛型介绍
  2. 清和
  3. 2022-03-29
  4. chenqh721@foxmail.com
  5. https://github.com/chenqinghe
  6. ## About the share
  7. 原文地址: [Type Parameters Proposal](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md)
  8. https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md
  9. - 当前版本的Go(1.18)并没有完全实现提案内容,可能有些许出入,会在后续版本中实现
  10. 本分享适用人群:
  11. - 英文阅读有障碍的人群
  12. - 喜欢看视频学习知识的人
  13. - 晚上睡不着想找点白噪音的人
  14. ## Agenda
  15. - Why generic
  16. - Type parameter
  17. - Constraint
  18. - More about type sets
  19. ## Why generic
  20. ## Why generic
  21. .code codes/atomic.go /OMIT/,/OMIT/
  22. - 大体逻辑都类似,仅参数类型不同
  23. - 每种类型都得实现一遍
  24. ## Why generic
  25. .code codes/atomic.go /INTR OMIT/,/INTR OMIT/
  26. - 需要写很多脏代码
  27. - 无法在编译期检查出错误
  28. - 类型转换影响性能
  29. ## How Generics (overview)
  30. ## Type parameters
  31. 泛型编程能够以一个抽象的类型的形式表示函数和数据结构,这个抽象的类型叫做`type parameter`(参数化类型). 在实际运行泛型代码的时候,会以实际类型来替换这个参数化类型。
  32. .code codes/print.go /PRINT OMIT/,/PRINT OMIT/
  33. 在Go中,希望每个标识符都能够通过某种方式来进行申明。
  34. 那么,如何来申明类型T?
  35. ## Type parameter
  36. - 在普通参数前面
  37. - 使用方括号[ ]包围
  38. - 类型参数也有「元类型」,也即constraint(约束)
  39. .code -edit codes/print.go /GEN OMIT/,/GEN OMIT/
  40. 以上示例代码中:
  41. - `T` 是一个**type parameter**
  42. - **any**是一个**constraint**,意思是T可以是任意类型
  43. - `T` 可以用来规定参数s的类型,也可以用在函数体内
  44. - 不同于普通参数,类型参数名`T` 不可省略
  45. ## Type parameter
  46. 调用泛型函数
  47. .play codes/print.go /CALL OMIT/,/CALL OMIT/
  48. - 需指定类型参数,类型参数写在中括号内
  49. - 有多个类型参数时,使用逗号分隔
  50. .code codes/print.go /CALL MULTI PARAMS OMIT/,/CALL MULTI PARAMS OMIT/
  51. ## Constraint
  52. ## Constraint
  53. 接下来来个稍微复杂点的例子:
  54. .play codes/stringfy.go /START OMIT/,/END OMIT/
  55. - T 可以是任意类型
  56. - 类型 T 可能并没有String方法
  57. **以上代码并不能运行**
  58. ## Constraint
  59. 在其他有泛型的语言中也会出现类似的情况。
  60. 例如,在C++中。
  61. 调用v.String()是允许的,在编译过程中,如果发现实际调用时传入的类型实参T没有String方法,那么会报错误,如果有String方法,可以正常编译。
  62. 也就是说:**C++实际上对传入类型是没有明确限制的**
  63. ## Constraint
  64. 出于语言风格考虑,Go语言不会采用上述方案。
  65. - In Go we don't refer to names, such as, in this case, String, and hope that they exist. Go resolves all names to their declarations when they are seen.
  66. - Another reason is that Go is designed to support programming at scale.
  67. Details see: [Type Parameters Proposal # Constraint](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#constraints)
  68. 通常,我们希望泛型代码中的类型参数满足一定的条件,这些条件被称为约束(Constraints)。
  69. Constraints必须能够同时限制调用方传入的类型参数以及泛型函数的具体实现:
  70. 1. **调用泛型函数时传入的类型实参必须满足Constraints**
  71. 2. **实现泛型函数时必须用Constraints允许的方式来使用这些值(e. g. + - * / > ....)**
  72. ## Summary
  73. 综上:
  74. - 函数除了普通参数外,可以额外的类型参数,类型参数使用`[]`包围
  75. - 这个类型参数可以作为普通参数的类型,也可以直接在函数体内使用
  76. - 每个参数类型都有个约束,就像普通参数都对应一个类型