关于指针的有限操作
- 传统意义上,指针是一个指向某个确切内存地址的值。这个地址可以是任何数据或者代码的起始地址。
- uintptr 也可以代表指针,它是一个数值类型。
- unsafe.Pointer 可以表示任何指向可寻址的值的指针。
- 不可变的值不可寻址,如常量、函数、方法的字面量。
- 绝大多数临时结果。
- 使用指针操作可能会破坏程序的一致性,这是不安全的。
- 你可以通过 unsafe 操纵指针,如下面这样获得一个执政值
dog := Dog{"little pig"}
dogP := &dog
dogPtr := uintptr(unsafe.Pointer(dogP))
- 使用它可以带来很多的灵活性,但是这种骚操作很不安全,所以建议不要这么做。
go 语句
- goroutine 代表并发模型中的用户级线程,我一般叫他协程。
- goroutine 的切换很快,切换成本很低,且不需要操作系统的调度,所以可以很灵活。
- 劣势在于,控制复杂。
go 中的系统级线程调度器 GPM
- G:goroutine 的缩写。
- P:processor 的缩写,它可以承载多个 G,并让它们与 M 对接。
-
M:machine 的缩写,即系统级线程。
image.png
它们之间有一套成熟的调度机制,对于这套机制,有机会我们详细了解一下。
range表达式
- 可以使用 range 迭代的:数组、数组的指针、切片、字符串、字典、通道等。
for...range
看下面一段代码:
numbers2 := [...]int{1, 2, 3, 4, 5, 6}
maxIndex2 := len(numbers2) - 1
for i, e := range numbers2 {
if i == maxIndex2 {
numbers2[0] += e
} else {
numbers2[i+1] += e
}
}
fmt.Println(numbers2) // [7 3 5 7 9 11]
为什么会是这个结果?在这里你有一些东西需要了解:
- for 语句被执行的时候,会有一个队 range 右边的变量复制的过程。
- 这个复制只有一次,不管这个变量有多少次迭代。
- range 的求值结果会被复制,也就是说,被迭代的对象是 range 结果值的副本,而不是原值。
根据上面的原理,你可以尝试理解下面的代码:
numbers2 := [...]int{1, 2, 3, 4, 5, 6}
maxIndex2 := len(numbers2) - 1
for i, e := range numbers2 {
if i == maxIndex2 {
numbers2[0] += e
} else {
numbers2[i+1] += e
}
}
fmt.Println(numbers2) // [7 3 5 7 9 11]
如果 number2 为切片,结果将会是 [22 3 6 10 15 21],你理解为什么吗?
网友评论