-
for range 鲜为人知的坑,其实以前用 php 的时候遇到过,Java 没有这个问题
// 因为 range 的时候,会创立一个长期变量 v 来承受 data 的遍历值 // 而不是你想的 append(&data[0], $data[1], ...) data := []int{1,2,3} result := []*int{} for _, v := range data {result = append(result, &v) fmt.Println(&v) // 0xc0000ac008,0xc0000ac008,0xc0000ac008 } for _, v := range result {fmt.Println(*v) // [3,3,3] } // 正确处理形式 data := []int{1,2,3} result := []*int{} for i, v := range data {result = append(result, &data[i]) } for _, v := range result {fmt.Println(*v) }
- 我的项目中函数返回值更多用的是构造体,而不是构造体指针。尽管这会进步内存拷贝开销,但另一方面能够升高 gc 压力。因为返回值如果用指针,那么变量会存储到堆,而不是栈,也就是产生了变量逃逸。
变量逃逸状况:
(1)函数中 new 或者字面量创立进去的变量,如果取变量指针作为函数返回值,那么该变量产生逃逸
(2)逃逸变量援用的指针逃逸
(3)被指针类型的 slice,map,chan 饮用的变量产生逃逸