2018-10-30
append
昨天上线完之后,线上报空指针.修改点如下:
但是在实际使用appInfoList的时候,报空指针,也就是取到的值为空.
把问题简化为以下的代码:
func InitSlice() {
slice1:=[]int{1,2,3,4,5,6,7,8,9,0}
slice2:=make([]*int,len(slice1))
for _,item:=range slice1{
slice2= append(slice2, &item)
}
fmt.Println(slice2)
}
输出结果为:[
所以出问题的地方在于slice的append方法
源码中append的说明:
// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
// slice = append(slice, elem1, elem2)
// slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
// slice = append([]byte("hello "), "world"...)
func append(slice []Type, elems ...Type) []Type
append在当前slice的末尾添加元素,添加测试代码:
func InitSlice() {
slice1:=[]int{1,2,3,4,5,6,7,8,9,0}
slice2:=make([]*int,len(slice1))
for index,item:=range slice1{
slice2= append(slice2, &item)
fmt.Println("size=", len(slice2),"index=",index)
}
}
输出为:
size= 11 index= 0 size= 12 index= 1 size= 13 index= 2 size= 14 index= 3 size= 15 index= 4 size= 16 index= 5 size= 17 index= 6 size= 18 index= 7 size= 19 index= 8 size= 20 index= 9
所以在确定元素个数的情况下,正确的实现:
func InitSlice() {
slice1:=[]int{1,2,3,4,5,6,7,8,9,0}
slice2:=make([]*int,len(slice1))
for index,item:=range slice1{
slice2[index]=&item
fmt.Println("size=", len(slice2),"index=",index)
}
}
简单的东西用的多了,就容易忽略它本身的含义.所以一开始还是应该好好打好基础,往往越是简单的东西排查起来越难.
2018-09-13
range
依旧是range
func main() {
var slice = make([]int64, 4)
slice[0] = 0
slice[1] = 1
slice[2] = 2
slice[3] = 3
for index, item := range slice {
fmt.Println(index, item)
}
var dataMap = make(map[int64](string))
dataMap[1] = "3"
dataMap[2] = "4"
dataMap[6] = "2"
//maps[1] = "d"
dataMap[8] = "adf"
dataMap[7] = "adf"
fmt.Println(dataMap)
for key, exist := range dataMap {
fmt.Println(key, exist)
}
}
通过以上测试代码可以看到:
对于go语言的map,顺序和放入的顺序一致;如果先后两次放入相同的key,则重复的key在整个map的最后
range遍历的时候,对于数组或切片,按照index遍历;对于map,顺序随机
2018-08-15
range
今天被range坑到了,看下边的代码:
func ReApplyService(c *gin.Context, applyId int64) (*common.ReApplyParam, error) {
params, err := service.GetAllServiceParams(c, &model.ServiceConfig{Name: applyInfo.ApplyServiceName})
if err == nil {
if applyInfo.AppId > 0 {
params, err = service.AddExistParamValues(c, params, applyInfo.AppId)
}
if err == nil {
var applyParam, err = sub_module.GetHandler(applyInfo.ApplyServiceName).ReApply(c, applyInfo.ApplyParams)
if err == nil {
if len(*applyParam) > 0 {
for _,item := range params {
if params[index].IsModifiable == 1 {
if (*applyParam)[strconv.Itoa(int(params[index].ID))] == nil {
item.Value = ""
} else {
item.Value = (*applyParam)[strconv.Itoa(int(item.ID))].(string)
}
}
}
}
result.Params = params
result.ServiceId = int64((data)[0].ID)
return &result, nil
}
}
}
logs.Error("reApply error:%v", err)
return nil, errors.New("get params error")
}
变量params
在这段代码中会做三次赋值,一次是通过GetAllServiceParams
,第二次是通过AddExistParamValues
,第三次则是在for
循环中,问题是,第三次赋值一直不成功,打日志后发现item.Value成功赋值,但result.Params是第二次赋值后的结果.最开始印象里记得看过一篇博客,说go会存在局部变量的问题,但似乎并不符合现在的情况.然后看到range,想起来range会创建一个新的切片,导致item的修改并不会影响到params.
这么说起来的话,用range做数组的遍历,会产生一个临时的切片,性能上来说不如直接用index做遍历好一点.
go跟java还是有区别的,不同语言间的切换还是有点不习惯