main.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package main
  2. import "fmt"
  3. type Student struct {
  4. Name string
  5. Age int
  6. }
  7. // 传入整数副本,只修改函数内部的 value。
  8. func changeValue(value int) {
  9. value = 100
  10. }
  11. // 指针参数本身也按值传递,但它指向调用方的整数。
  12. // 返回 bool 表示是否成功,避免解引用 nil 指针。
  13. func changeByPointer(value *int) bool {
  14. if value == nil {
  15. return false
  16. }
  17. *value = 100
  18. return true
  19. }
  20. // 给参数指针重新赋值,不会改变调用方指针本身。
  21. func redirect(value *int) {
  22. local := 999
  23. value = &local
  24. }
  25. // 结构体指针可以直接用点号访问字段,无需 C 风格的 ->。
  26. func birthday(student *Student) bool {
  27. if student == nil {
  28. return false
  29. }
  30. student.Age++ // 等价于 (*student).Age++。
  31. return true
  32. }
  33. func main() {
  34. // 1. & 取得变量地址;*int 表示“指向 int 的指针类型”。
  35. fmt.Println("=== 取地址与解引用 ===")
  36. number := 10
  37. var pointer *int = &number
  38. fmt.Printf("number 的值:%d\n", number)
  39. fmt.Printf("指针类型:%T,是否指向 number:%t\n", pointer, pointer == &number)
  40. fmt.Printf("通过 *pointer 读取:%d\n", *pointer)
  41. // 2. *pointer 在表达式中表示访问所指向的变量。
  42. *pointer = 20
  43. fmt.Printf("通过指针修改后,number:%d\n", number)
  44. // 3. 对比普通参数与指针参数。
  45. fmt.Println("\n=== 函数修改原变量 ===")
  46. changeValue(number)
  47. fmt.Printf("普通参数调用后:%d\n", number)
  48. ok := changeByPointer(&number)
  49. fmt.Printf("指针参数调用后:%d,成功:%t\n", number, ok)
  50. // 4. 复制指针仍指向同一变量;改指向和改内容是两回事。
  51. fmt.Println("\n=== 指针复制与重新指向 ===")
  52. alias := pointer
  53. *alias = 30
  54. fmt.Printf("通过 alias 修改后,number:%d\n", number)
  55. redirect(pointer)
  56. fmt.Printf("函数内重新指向后,原指针仍指向 number:%t\n", pointer == &number)
  57. // 5. 指针零值是 nil,没有指向有效变量时不能解引用。
  58. fmt.Println("\n=== nil 指针 ===")
  59. var empty *int
  60. fmt.Printf("空指针为 nil:%t\n", empty == nil)
  61. fmt.Printf("传入 nil,修改成功:%t\n", changeByPointer(empty))
  62. // fmt.Println(*empty) // 取消注释会导致运行时 panic。
  63. // 6. 结合结构体:通过指针修改原学生的年龄。
  64. fmt.Println("\n=== 结构体指针 ===")
  65. student := Student{Name: "小朱", Age: 20}
  66. birthday(&student)
  67. fmt.Printf("%s 过生日后,年龄:%d\n", student.Name, student.Age)
  68. // 7. new(int) 返回指向一个零值 int 的指针,不是 nil。
  69. fmt.Println("\n=== new 创建指针 ===")
  70. created := new(int)
  71. fmt.Printf("指针为 nil:%t,初始值:%d\n", created == nil, *created)
  72. *created = 42
  73. fmt.Printf("修改后的值:%d\n", *created)
  74. }