douou6696 2015-08-11 03:42
浏览 69
已采纳

Go的构造函数为什么要返回地址?

I understand that Go doesn't have any constructors and a New func is used in its place, but according to this example.

func NewFile(fd int, name string) *File {
  if fd < 0 {
    return nil
  }
  f := File{fd, name, nil, 0}
  return &f
}

They always return &f. Why just simply returning File isn't suffice?

Update

I've tried returning the created object for a simple struct and it's fine. So, I wonder if returning an address is a standard way of constructor or something.

Thanks.

  • 写回答

1条回答 默认 最新

  • duanchuang3182 2015-08-11 05:55
    关注

    As mentioned, yes, the spec allows you to return either values (as non-pointers) or pointers. It's just a decision you have to make.

    When to return pointer?

    Usually if the value you return is "more useful" as a pointer. When is it more useful?

    For example if it has many methods with pointer receiver. Yes, you could store the return value in a variable and so it will be addressable and you can still call its methods that have pointer receivers. But if a pointer is returned right away, you can "chain" method calls. See this example:

    type My int
    
    func (m *My) Str() string { return strconv.Itoa(int(*m)) }
    
    func createMy(i int) My { return My(i) }
    

    Now writing:

    fmt.Println(createMy(12).Str())
    

    Will result in error: cannot call pointer method on createMy(12)

    But if works if you return a pointer:

    func createMy(i int) *My { return (*My)(&i) }
    

    Also if you store the returned value in a data structure which is not addressable (map for example), you cannot call methods on values by indexing a map because values of a map are not addressable.

    See this example: My.Str() has pointer receiver. So if you try to do this:

    m := map[int]My{0: My(12)}
    m[0].Str() // Error!
    

    You can't because "cannot take the address of m[0]". But the following works:

    m := map[int]*My{}
    my := My(12)
    m[0] = &my // Store a pointer in the map
    
    m[0].Str() // You can call it, no need to take the address of m[0]
               // as it is already a pointer
    

    And another example for pointers being useful is if it is a "big" struct which will be passed around a lot. http.Request is a shining example. It is big, it is usually passed around a lot to other handlers, and it has methods with pointer receiver.

    If you return a pointer, that usually suggests that the returned value is better if stored and passed around as a pointer.

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

报告相同问题?

悬赏问题

  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程