douwo6738 2016-05-25 19:57
浏览 64
已采纳

在结构上调用函数的正确的go习惯用法是什么?

I am new to go (coming from python and ruby) and want to know what is the idiomatic way of calling functions on a struct?

Mostly I want to know if I should use the dot operator to call functions or use my type as one of the arguments. Also is it better to use pointers or not?

  • pointer vs no pointer?
  • dot vs argument? *

I can do it this way?

package main

import "fmt"

func main() {
    me := Person{firstname: "John", lastname: "Doe", age: 40}
    fmt.Println(me.fullname())
}

type Person struct {
    firstname string
    lastname  string
    age       int
}

func (p Person) fullname() string {
    return p.firstname + p.lastname
}

or this way

package main

import "fmt"

func main() {
    me := Person{firstname: "John", lastname: "Doe", age: 40}
    fmt.Println(fullname(&me))
}

type Person struct {
    firstname string
    lastname  string
    age       int
}

func fullname(p *Person) string {
    return p.firstname + p.lastname
}
  • 写回答

1条回答 默认 最新

  • duanqiao0153 2016-05-25 20:13
    关注

    There isn't one correct way of doing this. It's important to understand the differences between the two and apply each where appropriate. Further more, your functions aren't really comparable. In the one case you've defined a function with a receiver of type Person and it is passed by value, meaning a copy of the instance is made and pushed onto the stack. In the other instance the function is stand alone and you pass a Person reference to it. You can also, do pass by reference with an 'instance method' by making the receiving type a pointer.

    So in the first case;

    func (p Person) fullname() string {
        return p.firstname + p.lastname
    }
    

    you call the function like p.fullname() and a copy of p is pushed onto the stack. If you did assignment in this function, p would not be modified, the instance in the scope would be modified. So for setters, or any function that is intended to change the objects state, this isn't an option at all.

    To elaborate on the alternative I was talking about, you could instead do this;

    func (p *Person) fullname() string {
        return p.firstname + p.lastname
    }
    

    Which still allow you to call it on an instance like p.fullname() however, what's passed to the function is a reference of type *Person. So this would be the typical choice for implementing a function that sets a value on a struct.

    Now your second example;

    func fullname(p *Person) string {
        return p.firstname + p.lastname
    }
    

    has no receiver and passes a pointer. Meaning you call it like this fullname(p). The function is not exported so it's only available in the package where it was declared, in this case main. To draw parallels to (potentially) more familiar languages, this is like defining a function in C++ where the other two are defining a 'method' or a function in a class. And the other two would be compared to 'passing by value' or 'passing by reference'. This passes by reference by is no associated to any type.

    In your example I would always use func (p *Person) fullname() string for performance reasons. In my opinion the most appropriate time to use the pass by value alternative func (p Person) fullname() string is when you want to enforce immutability. If you want to do operations where it's better to produce a new object rather than modifying an existing one (a lot of collection libraries operate like this, for example LINQ in C# always produces a new collection and an attempt to modify the collection during a query will result in an exception) then you probably want a value type receiver.

    Hope that helps. I can update with more information if any of this is still the cause of confusion.

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

报告相同问题?

悬赏问题

  • ¥20 keepalive配置业务服务双机单活的方法。业务服务一定是要双机单活的方式
  • ¥50 关于多次提交POST数据后,无法获取到POST数据参数的问题
  • ¥15 win10,这种情况怎么办
  • ¥15 如何在配置使用Prettier的VSCode中通过Better Align插件来对齐等式?(相关搜索:格式化)
  • ¥100 在连接内网VPN时,如何同时保持互联网连接
  • ¥15 MATLAB中使用parfor,矩阵Removal的有效索引在parfor循环中受限制
  • ¥20 Win 10 LTSC 1809版本如何无损提升到20H1版本
  • ¥50 win10 LTSC 虚拟键盘不弹出
  • ¥30 微信小程序请求失败,网页能正常带锁访问
  • ¥15 Matlab求解微分方程,如何用fish2d进行预优?