main.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package main
  2. import "fmt"
  3. type Student struct {
  4. Name string
  5. Age int
  6. Score float64
  7. }
  8. // 1. 普通函数:学生作为普通参数传入。
  9. func describe(student Student) string {
  10. return fmt.Sprintf("%s,年龄:%d,成绩:%.1f", student.Name, student.Age, student.Score)
  11. }
  12. // 2. 方法:func 后面的 (student Student) 称为接收者。
  13. // 值接收者接收 Student 值的副本,这个方法只读取字段。
  14. func (student Student) Summary() string {
  15. return fmt.Sprintf("%s,年龄:%d,成绩:%.1f", student.Name, student.Age, student.Score)
  16. }
  17. // 3. 值接收者中修改整数,只修改副本,不改变原学生。
  18. func (student Student) TryBirthday() {
  19. student.Age++
  20. }
  21. // 4. 指针接收者可以通过指针修改原学生。
  22. // 本方法约定允许 nil,返回 false 表示没有可修改的学生。
  23. func (student *Student) Birthday() bool {
  24. if student == nil {
  25. return false
  26. }
  27. student.Age++
  28. return true
  29. }
  30. // 5. 方法也能接收普通参数,并通过返回值报告是否成功。
  31. func (student *Student) SetScore(score float64) bool {
  32. // 这种写法同时拒绝不在范围内的值和 NaN。
  33. if student == nil || !(score >= 0 && score <= 100) {
  34. return false
  35. }
  36. student.Score = score
  37. return true
  38. }
  39. func main() {
  40. student := Student{Name: "小朱", Age: 20, Score: 85}
  41. fmt.Println("=== 普通函数与方法 ===")
  42. fmt.Println("普通函数:", describe(student))
  43. fmt.Println("方法调用:", student.Summary())
  44. fmt.Println("\n=== 值接收者 ===")
  45. student.TryBirthday()
  46. fmt.Printf("调用 TryBirthday 后,原年龄:%d\n", student.Age)
  47. fmt.Println("\n=== 指针接收者 ===")
  48. // student 是可以取地址的变量,Go 自动把调用理解为 (&student).Birthday()。
  49. ok := student.Birthday()
  50. fmt.Printf("调用 Birthday 后,年龄:%d,成功:%t\n", student.Age, ok)
  51. fmt.Println("\n=== 方法参数与返回值 ===")
  52. ok = student.SetScore(95)
  53. fmt.Printf("设置 95 分:成功=%t,当前成绩=%.1f\n", ok, student.Score)
  54. ok = student.SetScore(120)
  55. fmt.Printf("设置 120 分:成功=%t,当前成绩=%.1f\n", ok, student.Score)
  56. fmt.Println("\n=== 通过指针调用方法 ===")
  57. pointer := &student
  58. // *Student 也可以调用值接收者的方法,前提是这里指针非 nil。
  59. fmt.Println(pointer.Summary())
  60. fmt.Println("\n=== nil 指针接收者 ===")
  61. var empty *Student
  62. fmt.Printf("nil 调用 Birthday:%t\n", empty.Birthday())
  63. fmt.Printf("nil 调用 SetScore:%t\n", empty.SetScore(80))
  64. // empty.Summary() 不能安全调用:值接收者需要取得 Student 值。
  65. }