mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-12 05:33:04 +08:00
@@ -9,17 +9,17 @@
|
|||||||
Go 语言的取地址符是 `&`,放到一个变量前使用就会返回相应变量的内存地址。
|
Go 语言的取地址符是 `&`,放到一个变量前使用就会返回相应变量的内存地址。
|
||||||
|
|
||||||
下面的代码片段(示例 4.9 [pointer.go](examples/chapter_4/pointer.go))可能输出 `An integer: 5, its location in memory: 0x6b0820`(这个值随着你每次运行程序而变化)。
|
下面的代码片段(示例 4.9 [pointer.go](examples/chapter_4/pointer.go))可能输出 `An integer: 5, its location in memory: 0x6b0820`(这个值随着你每次运行程序而变化)。
|
||||||
|
|
||||||
```go
|
```go
|
||||||
var i1 = 5
|
var i1 = 5
|
||||||
fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1)
|
fmt.Printf("An integer: %d, it's location in memory: %p\n", i1, &i1)
|
||||||
```
|
```
|
||||||
|
|
||||||
这个地址可以存储在一个叫做指针的特殊数据类型中,在本例中这是一个指向 int 的指针,即 `i1`:此处使用 *int 表示。如果我们想调用指针 intP,我们可以这样声明它:
|
这个地址可以存储在一个叫做指针的特殊数据类型中,在本例中这是一个指向 int 的指针,即 `i1`:此处使用 *int 表示。如果我们想调用指针 intP,我们可以这样声明它:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
var intP *int
|
var intP *int
|
||||||
```
|
```
|
||||||
|
|
||||||
然后使用 `intP = &i1` 是合法的,此时 intP 指向 i1。
|
然后使用 `intP = &i1` 是合法的,此时 intP 指向 i1。
|
||||||
|
|
||||||
@@ -41,10 +41,10 @@ intP 存储了 i1 的内存地址;它指向了 i1 的位置,它引用了变
|
|||||||
|
|
||||||
对于任何一个变量 var, 如下表达式都是正确的:`var == *(&var)`。
|
对于任何一个变量 var, 如下表达式都是正确的:`var == *(&var)`。
|
||||||
|
|
||||||
现在,我们应当能理解 pointer.go 中的整个程序和他的输出:
|
现在,我们应当能理解 pointer.go 的全部内容及其输出:
|
||||||
|
|
||||||
示例 4.21 [pointer.go](examples/chapter_4/pointer.go):
|
示例 4.21 [pointer.go](examples/chapter_4/pointer.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
import "fmt"
|
import "fmt"
|
||||||
@@ -54,7 +54,7 @@ func main() {
|
|||||||
var intP *int
|
var intP *int
|
||||||
intP = &i1
|
intP = &i1
|
||||||
fmt.Printf("The value at memory location %p is %d\n", intP, *intP)
|
fmt.Printf("The value at memory location %p is %d\n", intP, *intP)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
输出:
|
输出:
|
||||||
@@ -71,7 +71,7 @@ func main() {
|
|||||||
它展示了分配一个新的值给 *p 并且更改这个变量自己的值(这里是一个字符串)。
|
它展示了分配一个新的值给 *p 并且更改这个变量自己的值(这里是一个字符串)。
|
||||||
|
|
||||||
示例 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go)
|
示例 4.22 [string_pointer.go](examples/chapter_4/string_pointer.go)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
import "fmt"
|
import "fmt"
|
||||||
@@ -83,7 +83,7 @@ func main() {
|
|||||||
fmt.Printf("Here is the string *p: %s\n", *p) // prints string
|
fmt.Printf("Here is the string *p: %s\n", *p) // prints string
|
||||||
fmt.Printf("Here is the string s: %s\n", s) // prints same string
|
fmt.Printf("Here is the string s: %s\n", s) // prints same string
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
输出:
|
输出:
|
||||||
|
|
||||||
@@ -100,12 +100,12 @@ func main() {
|
|||||||
**注意事项**
|
**注意事项**
|
||||||
|
|
||||||
你不能得到一个文字或常量的地址,例如:
|
你不能得到一个文字或常量的地址,例如:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
const i = 5
|
const i = 5
|
||||||
ptr := &i //error: cannot take the address of i
|
ptr := &i //error: cannot take the address of i
|
||||||
ptr2 := &10 //error: cannot take the address of 10
|
ptr2 := &10 //error: cannot take the address of 10
|
||||||
```
|
```
|
||||||
|
|
||||||
所以说,Go 语言和 C、C++ 以及 D 语言这些低级(系统)语言一样,都有指针的概念。但是对于经常导致 C 语言内存泄漏继而程序崩溃的指针运算(所谓的指针算法,如:`pointer+2`,移动指针指向字符串的字节数或数组的某个位置)是不被允许的。Go 语言中的指针保证了内存安全,更像是 Java、C# 和 VB.NET 中的引用。
|
所以说,Go 语言和 C、C++ 以及 D 语言这些低级(系统)语言一样,都有指针的概念。但是对于经常导致 C 语言内存泄漏继而程序崩溃的指针运算(所谓的指针算法,如:`pointer+2`,移动指针指向字符串的字节数或数组的某个位置)是不被允许的。Go 语言中的指针保证了内存安全,更像是 Java、C# 和 VB.NET 中的引用。
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ ptr2 := &10 //error: cannot take the address of 10
|
|||||||
对一个空指针的反向引用是不合法的,并且会使程序崩溃:
|
对一个空指针的反向引用是不合法的,并且会使程序崩溃:
|
||||||
|
|
||||||
示例 4.23 [testcrash.go](examples/chapter_4/testcrash.go):
|
示例 4.23 [testcrash.go](examples/chapter_4/testcrash.go):
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
func main() {
|
func main() {
|
||||||
@@ -131,7 +131,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
// in Windows: stops only with: <exit code="-1073741819" msg="process crashed"/>
|
// in Windows: stops only with: <exit code="-1073741819" msg="process crashed"/>
|
||||||
// runtime error: invalid memory address or nil pointer dereference
|
// runtime error: invalid memory address or nil pointer dereference
|
||||||
```
|
```
|
||||||
|
|
||||||
**问题 4.2** 列举 Go 语言中 * 号的所有用法。
|
**问题 4.2** 列举 Go 语言中 * 号的所有用法。
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user