

在计算机的内存华府里,每一个变量都有一个专属的房间。
0xc000010200)。想知道变量住在哪里?在它面前加个 &。
name := "秋香"
// addr 是 address 的缩写
// &name 意思是:获取 name 的门牌号
addr := &name
fmt.Printf("房客名字: %s\n", name) // 秋香
fmt.Printf("房间地址: %v\n", addr) // 0xc000010200 (每次运行可能不一样)
专门用来存“门牌号”的变量,叫指针变量。
// 定义一个指针变量 ptr,它指向 string 类型
// *string 表示这是一个“存放字符串地址”的盒子
var ptr *string = &name
拿到了门牌号(指针),怎么找里面的人呢?用 * 号!这叫解引用 (Dereference)。
fmt.Println("地址是:", ptr)
fmt.Println("住的人是:", *ptr) // 输出:秋香
// ⚠️ 还能隔空改名!
// *ptr = "..." 意思是:找到 ptr 指向的那个房间,把里面的人换掉
*ptr = "石榴姐"
fmt.Println(name) // 输出:石榴姐 (原来的 name 真的变了!)
这是 Go 语言最重要的一课!Go 语言只有值传递(Pass by Value)。
如果你传的是变量,Go 会复印一份给你;如果你传的是指针(地址),Go 也会复印一份“地址纸条”给你——但这张纸条指向的房间是同一个!

func modifyValue(s string) {
s = "经过整容"
}
func modifyPointer(s *string) {
*s = "经过整容"
}
func main() {
face := "如花"
// 1. 传值(给复印件)
modifyValue(face)
fmt.Println(face) // 输出:如花 (根本没变)
// 2. 传地址(给坐标)
modifyPointer(&face)
fmt.Println(face) // 输出:经过整容 (变了!)
}
有时候我们想先占个坑,以后再住人。可以使用 new() 函数。
// new(int) 会做两件事:
// 1. 在内存分配一个 int 类型的空间
// 2. 把它初始化为 0
// 3. 返回这个空间的地址指针
ptr := new(int)
fmt.Println(ptr) // 输出地址 (如 0xc0000...)
fmt.Println(*ptr) // 输出 0 (默认值)
*ptr = 9527 // 填入数据
fmt.Println(*ptr) // 输出 9527
func createGift() *string {
gift := "唐寅诗集" // 局部变量
return &gift // 返回局部变量的地址
}
func main() {
// 在 C 语言里这就崩了,但在 Go 里是安全的!
p := createGift()
fmt.Println(*p) // 输出:唐寅诗集
}
如果一个指针没有指向任何房间,它就是 nil(空)。试图去开一个不存在的房间的门,会直接报错(Panic)!

var p *int // 声明了但没赋值,默认是 nil
// fmt.Println(*p) // 💥 报错!panic: runtime error: invalid memory address or nil pointer dereference
// ✅ 正确做法:先判断
if p != nil {
fmt.Println(*p)
} else {
fmt.Println("这是一个空指针,不能用!")
}
编写一个函数 swap,交换两个整数变量的值。(提示:如果不传指针,是换不掉的哦)
package main
import "fmt"
// 填空:参数类型应该是什么?
func swap(a _____, b _____) {
temp := *a
*a = *b
*b = temp
}
func main() {
x, y := 1, 2
// 填空:怎么传参?
swap(____, ____)
fmt.Println(x, y) // 期望输出:2 1
}
任务: 补全代码,实现交换。
答案:
func swap(a *int, b *int) { ... }
swap(&x, &y)
只有通过指针(地址),才能真正交换两个变量肚子里的值。