douzhi9395 2015-01-01 19:19
浏览 8
已采纳

嵌入何时使用指针

When I want to embed a struct within another struct, should I use a pointer or value?

For example

type Job struct {
    Command string
    *log.Logger
}

or

type Job struct {
    Command string
    log.Logger
}
  • 写回答

1条回答 默认 最新

  • dsmvovm27249 2015-01-01 19:34
    关注

    You can use one or the other: for struct type, the spec mentions:

    A field declared with a type but no explicit field name is an anonymous field, also called an embedded field or an embedding of the type in the struct.

    An embedded type must be specified as a type name T or as a pointer to a non-interface type name *T, and T itself may not be a pointer type.

    Since log.Logger is not an interface, you can use the type or a pointer to the type for the anonymous field Logger.


    The article "Embedding in Go " fro Eric Urban (hydrogen18) calls embedding a pointer "embed by-pointer":

    • The first advantage to this is that you can rely on functions that use the NewX idiom returning a struct by-pointer to do initialization.
    • The second advantage is that you can embed all the functionality of a type without needing to know when it is instantiated.
      The embedded pointer to a Bitmap is no different than any other pointer in Go, so it can be assigned multiple times.
      By doing this you can change what instance you are extending dynamically at run time.

    For instance, with:

    type Bitmap struct{
        data [4][5]bool
    }
    
    type Renderer struct{
        *Bitmap //Embed by pointer
        on uint8
        off uint8
    }
    

    The Renderer type embeds a Bitmap by-pointer.

    A single instance of Bitmap can act as the embedded instance of many Renderer instances:

    var renderA,renderB Renderer
    renderA.on = 'X'
    renderA.off = 'O'
    renderB.on = '@'
    renderB.off = '.'
    
    var pic Bitmap
    pic.data[0][6] = true
    pic.data[0][7] = true
    pic.data[1][8] = true
    pic.data[2][9] = true
    pic.data[3][10] = true
    
    renderA.Bitmap = &pic
    renderB.Bitmap = &pic
    
    renderA.render()
    renderB.render()
    

    This shares the same Bitmap instance to two different renderers.
    Each renderer has its own set of characters, allowing two representations of the bitmap to be printed.
    This is what the output looks like:

    OXXO
    OXOO
    OXOO
    OXOO
    .@@.
    .@..
    .@..
    .@..
    

    This example demonstrates the Flyweight Pattern.
    Although inconsequential to memory consumption in this example, having many thousands of instances sharing a single underlying data structure can be very significant in reducing the memory consumption of systems.


    As mentioned in this thread:

    The reason why you can't have pointer to pointer and pointer to interface anonymous fields is that these types don't have methods.
    The whole point of anonymous fields is that methods get promoted.

    I already explained why interfaces don't have methods: a lot of people were using pointers to interfaces incorrectly and unnecessarily, and there weren't any known valid uses, so the language was changed to actively discourage this usage by making pointers to interfaces have no methods.

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

报告相同问题?

悬赏问题

  • ¥15 公交车和无人机协同运输
  • ¥15 stm32代码移植没反应
  • ¥15 matlab基于pde算法图像修复,为什么只能对示例图像有效
  • ¥100 连续两帧图像高速减法
  • ¥15 组策略中的计算机配置策略无法下发
  • ¥15 如何绘制动力学系统的相图
  • ¥15 对接wps接口实现获取元数据
  • ¥20 给自己本科IT专业毕业的妹m找个实习工作
  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)