问 fun1 和 fun2 fun3分别输出什么,为什么?
```go
func fun1() {
a := 2
c := (*string) (unsafe.Pointer(&a))
*c = "44"
fmt.Println(*c)
}
func fun2() {
a := "654"
c := (*string) (unsafe.Pointer(&a))
*c = "44"
fmt.Println(*c)
}
func fun3() {
a := 3
c := *(*string) (unsafe.Pointer(&a))
c = "445"
fmt.Println(c)
}
```
并不是因为调用了 fmt.Println(&b) 才导致b的内存被用到c里面。
b这个变量分配出来的时候就在a的后面,强转c的时候一定会溢出到b
调用 fmt.Println(&b) 是为了保证让编译器不把b给优化掉啊, 也能保证b这个变量不被提前GC回收掉
编译器在处理简单逻辑时有可能会把一些操作给优化掉,只要保证语言层面逻辑不发生变化就可以。
上述代码显示的对b进行取地址操作,并且把这个地址传递给了其他函数,编译器在编译的时候发现了这个,就一定会保证b这个变量确实被分配出来,并且不会马上销毁。
如果你写这样的代码
a := 1
fmt.Println(a)
b := 2
fmt.Println(b)
如果a和b变量在之后的代码中再也不使用,那编译器很可能会把它优化为
fmt.Println(1)
fmt.Println(2)
因为你调用时只是值传递,所以这样的逻辑上跟上面代码没有任何区别。
当然我对Go编译器的优化过程并不是非常了解,以上只是根据经验推测。
但实测下来编译器确实会做类似的优化,有可能一个变量,在编译器发现它完全没用了之后会立刻把它销毁掉把内存还给其他变量用的
#44
更多评论
```go
func fun1() {
a := 2
c := (*string) (unsafe.Pointer(&a)) //c为a的unsafe.pointer强制转为string指针,*c指的是a的值,a的值是int型的,这里*c = "44"是强制赋了个字符串,所以赋值是失败的,只是没有提示,因为使用了unsafe
*c = "44"
fmt.Println(*c) //这时的c是string指针,*c指的应该是一个字符串,但是里面实际上是int数据,所以操作也是失败的
}
func fun2() {
a := "654"
c := (*string) (unsafe.Pointer(&a)) //根据fun1的解释 a 为字符串型,那整个流程就通了,自然*c打出来的是 44,在*c="44"上面打印出来的是肯定是654
*c = "44"
fmt.Println(*c)
}
func fun3() {
a := 3
c := *(*string) (unsafe.Pointer(&a)) //这里获取的是a地址里的string值,但a的值是int型,所以操作失败,没有得到值,但c被定义里了string型变量,c = "445",给string型变量赋string值 自然是正常的
c = "445"
fmt.Println(c)
}
```
#1