dsdtumf776629385 2018-07-16 07:41
浏览 394
已采纳

golang从指针类型切片复制指针值

type Order struct {
    *Res
    Status int
}

type Res struct {
    ResID            int64
    OtaBookID        string
    StayDetail       []*ResElement
    TotalCharge      float64
    CustFName        string
    CustLName        string
    CreateTime       time.Time
}

type ResElement struct {
    Res        *Res
    OtaEleID   string
    OtaRoomID  string
    RoomID     int
    Arrival    time.Time
    Depart     time.Time
    Charge     float64
    CreateTime time.Time
}

I have a slice named orderList to record orders. Now i have the first order which OtaBookID is "A123", and i want to copy this order and change its OtaBookID to "B123". The ResElement type have some other detail info to record this order and i hide them because it not affect my question. I can success change Res.OtaBookID but i have no idea how to change Res.StayDetail[0].Res.OtaBookID

func main() {
    var orderList []*Order

    res := new(Res)
    res.OtaBookID = "A123"

    resElt := new(ResElement)
    resElt.Res = res
    res.StayDetail = append(res.StayDetail, resElt)

    order := new(Order)
    order.Res = res

    orderList = append(orderList, order)

    originalOrder := new(Order)
    originalOrder.Res = new(Res)
    *originalOrder.Res = *order.Res
    //originalOrder.Res.StayDetail[0].Res.OtaBookID = "B123" //this will make all become "B123"

    originalOrder.Res.OtaBookID = "B123"

    orderList = append(orderList, originalOrder)

    fmt.Println(orderList[0].Res.OtaBookID)  //A123
    fmt.Println(orderList[1].Res.OtaBookID)  //B123
    fmt.Println(orderList[0].Res.StayDetail[0].Res.OtaBookID)  //A123
    fmt.Println(orderList[1].Res.StayDetail[0].Res.OtaBookID)  //A123, i want this become B123
}

The result i want is orderList[0].Res.OtaBookID and orderList[0].Res.StayDetail[0].Res.OtaBookID is "A123" and other is "B123"

ps: Because i'm taking over other's works. So the three type already fixed and can not adjust. I want to know in this situation whether have any method to arrive my goal

  • 写回答

1条回答 默认 最新

  • douji1077 2018-07-16 21:30
    关注

    From your example and clarification we can focus on main to achieve your goal:

    type Order struct {
        *Res
        Status int
    }
    
    type Res struct {
        ResID            int64
        OtaBookID        string
        StayDetail       []*ResElement
        TotalCharge      float64
        CustFName        string
        CustLName        string
        CreateTime       time.Time
    }
    
    type ResElement struct {
        Res        *Res
        OtaEleID   string
        OtaRoomID  string
        RoomID     int
        Arrival    time.Time
        Depart     time.Time
        Charge     float64
        CreateTime time.Time
    }
    
    func main() {
        var orderList []*Order
    
        res := new(Res)
        res.OtaBookID = "A123"
    
        resElt := new(ResElement)
        resElt.Res = res
        res.StayDetail = append(res.StayDetail, resElt)
    
        order := new(Order)
        order.Res = res
    
        orderList = append(orderList, order)
    
        originalOrder := new(Order)
        originalOrder.Res = new(Res)
    
        // The following statement will copy the values in the memory space of order to the memory
        // space of originalOrder, but take note that a pointer contains a memory address. Thus,
        // following this statement originalOrder.Res.StayDetail will point to the same address
        // as order.Res.StayDetail as slices are pointers...
        *originalOrder.Res = *order.Res
    
        // We now have to manually copy the slice to ensure it is different from the one in order.
        // We must create a new slice to avoid overwriting the source.
        originalOrder.Res.StayDetail := make([]*ResElement, len(order.Res.StayDetail))
    
        // Further, this slice contains pointers so we must copy these as well to ensure they do not
        // point to the ResElements of order.
        for i, v := range order.Res.StayDetail {
            re := new(ResElement)
    
            // copy the values of the memory in v to the values in the memory of re
            *re = *v
    
            // set re.Res to point to originalOrder.Res as it currently point to order.Res
            re.Res = originalOrder.Res
    
            // Now we must place re in the slice of originalOrder as it currently points to an
            // empty array of the correct size. Thus, we will not use append (which will grow
            // the size), we will just set the index to the correct value. Thus:
            originalOrder.StayDetail[i] = re
        }
        // The pointers and structures have now been properly set up, thus the following are equivalent:
        // originalOrder.OtaBookID = "B123" - Res via embedding
        // originalOrder.Res.OtaBookID = "B123" - Res directly
        // originalOrder.Res.StayDetail[0].Res.OtaBookID = "B123" - Res via ResElement pointer Res
        // They all point to the exact same memory space
    
        originalOrder.Res.OtaBookID = "B123"
    
        orderList = append(orderList, originalOrder)
    
        fmt.Println(orderList[0].Res.OtaBookID)  //A123
        fmt.Println(orderList[1].Res.OtaBookID)  //B123
        fmt.Println(orderList[0].Res.StayDetail[0].Res.OtaBookID)  //A123
        fmt.Println(orderList[1].Res.StayDetail[0].Res.OtaBookID)  //B123
    }
    

    Always remember that a pointer is just a memory address. If the address value is 0xffab67e1 a copy of the pointer will also contain the same value of 0xffab67e1 and effectively point to the same thing. Thus you must deliberately assign new memory space at a new address and copy the internal values. This must be done for any structures that contain pointers. We call this a Deep Copy or a Clone.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作