golang语法-----指针
一、核心语法
1、取地址符 &,
用在一个变量前面,获取这个变量的内存地址。
package mainimport "fmt"func main() {name := "Alice" // 变量 name,它的值是 "Alice"// &name 获取变量 name 的内存地址// p 是一个指针变量,它存储了 name 的地址// p 的类型是 *string,读作 "string 类型的指针"p := &name fmt.Println("变量 name 的值:", name)fmt.Println("变量 name 的内存地址:", p) // 会打印一个像 0x... 的十六进制地址
}
2、解引用符 *,
用在一个指针变量前面,获取该指针指向的地址上存储的那个值。
// ... p 是指向 name 的指针// *p 表示“访问 p 指针指向的那个变量的值”fmt.Println("通过指针 p 访问到的值:", *p) // 输出: Alice// 通过指针修改原变量的值*p = "Bob" // 这等价于 name = "Bob"fmt.Println("修改后,原变量 name 的值:", name) // 输出: Bobfmt.Println("修改后,通过指针 p 访问到的值:", *p) // 输出: Bob
3、空指针,当一个指针被定义后没有分配到任何变量时,它的值为 nil
package mainimport "fmt"func main() {var p *stringfmt.Println(p)fmt.Printf("p的值是%s/n", p)if p != nil {fmt.Println("非空")} else {fmt.Println("空值")}
}
4、安全特性
(1)无指针运算:不允许像在 C 语言里那样对指针进行加减运算(例如 p++
),杜绝了一大类内存访问错误。
你只能从一个指针移动到另一个指针(通过 unsafe
包,但新手绝对不要碰)。
(2)无法获取任意地址的指针: 不能将一个整数强制转换成指针,无法指向任意内存地址。
二、指针的应用
1、在函数间共享和修改数据
Go 语言的函数参数传递都是值传递,意味着把一个变量传给函数时,函数得到的是这个变量的一个副本,比如:
func changeValue(num int) {num = 100 // 这里修改的是 num 的副本,不会影响外面的 a
}func main() {a := 10changeValue(a)fmt.Println("a 的值是:", a) // 输出: a 的值是: 10
}
通过传递变量的地址(指针),函数就可以通过地址直接操作原始变量,而不是它的副本:
// 函数接收一个 *int 类型的参数,即一个指向 int 的指针
func changeValueByPointer(ptr *int) {*ptr = 100 // 通过指针,直接修改了指针指向地址上的值
}func main() {a := 10changeValueByPointer(&a) // 把 a 的内存地址传给函数fmt.Println("a 的值是:", a) // 输出: a 的值是: 100
}
2、指向结构体的指针
type Person struct {Name stringAge int
}func main() {p := Person{Name: "David", Age: 40}// a. 创建一个指向结构体的指针ptr := &p// b. 访问结构体字段// 标准写法是 (*ptr).Name,需要解引用再访问字段fmt.Println("姓名:", (*ptr).Name)// c. 语法糖 (Syntactic Sugar)// Go 语言为了方便,允许你直接用 ptr.Name 来代替 (*ptr).Name// 编译器会自动帮你转换。这种写法更常用!fmt.Println("姓名 (语法糖):", ptr.Name) // 通过指针修改字段ptr.Age = 41fmt.Println("修改后的年龄:", p.Age) // 输出: 41
}
3、new
函数:创建指针
除了用 &
获取已有变量的地址,你还可以用内置的 new
函数来创建一个指向某个类型零值的指针。
new(T)
的作用是:
- 分配一块内存来存储
T
类型的零值。 - 返回这块内存的地址,即一个
*T
类型的指针。
// 创建一个指向 int 零值 (0) 的指针
var p1 = new(int)
fmt.Println("p1 指向的值:", *p1) // 输出: 0
*p1 = 123
fmt.Println("修改后 p1 指向的值:", *p1) // 输出: 123// 创建一个指向 Person 零值的指针
var p2 = new(Person)
p2.Name = "Eve"
fmt.Println("p2 指向的人:", *p2) // 输出: {Eve 0}