dthyxna3894 2016-12-29 12:06
浏览 94
已采纳

在导入包中定义struct时如何使用go接收器

currently working with the vishvananda/netns package trying to extract routes from a specific network namespace.

There is a defined Handle struct which is returned when I request a 'handle' for a specific network namespace. As such:

func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error)

This is then a receiver argument (?) to a function that requires that handle,

func (h *Handle) LinkList() ([]Link, error)

I'm new to go and not sure how to tie these together. I'm stuck with:

func (h *Handle) showInts() {
  int, err := h.netlink.LinkList()
  if err != nil {
      log.Fatal(err)
  }

  for i, r := range int {
      log.Printf("%d: %s", i, r.Attrs().Name)
  }
}


func main() {
    ints, err := netlink.LinkList()
    if err != nil {
        log.Fatal(err)
    }
    for i, r := range ints {
        log.Printf("%d: %s", i, r.Attrs().Name)
    }

    pid, err := netns.GetFromPid(9097)
    if err != nil {
        log.Fatal(err)
    }

    netlink.NewHandleAt(pid)
    showInts()
}
  • 写回答

2条回答 默认 最新

  • doumengxue7371 2016-12-29 13:14
    关注

    Update

    While writing the original answer, touched on a number of things, without any clear structure, so here's a more structured version:

    Depending on what you're actually asking (ie "How do I add a receiver function/method to an exported type", or "What the hell is a receiver function"), the answers are as follows:

    How do I add a receiver function to an exported type?

    Easy, same as you do with any other type. You were close, in fact. This doesn't work:

    func (h *Handler) showInts() {}
    

    Because you're adding a method to the Handler type in your package. Given you have a main function, that would be the main package. You're trying to add it to the netlink.Handler type instead. In which case, this will work:

    func (h *netlink.Handler) showInts(){}
    

    The type is netlink.Handler in your main package after all... This, however will not work. The compiler will refuse to compile, telling you: "Cannot define new methods on non-local type". This is easily mitigated, though, by creating a new type, and add the method there:

    type MyHandler netlink.Handler
    func (h *MyHandler) showInts(){}
    

    Be that as it may, the last 2 lines in your code strike me as wrong. Given that NewHandleAt returns (*Handle, error), and netlink.Handle is a receiver argument, the correct way would be:

    var mh *MyHandle
    if h, err := netlink.NewHandleAt(pid); err != nil {
        log.Fatal(err) // something went wrong
    } else {
        mh = (*MyHandle)(h)
    }
    mh.showInts() // call showInts on mh, which is of type *MyHandle
    

    The fact that you've "wrapped" the external type in a custom type does mean you'll find yourself casting the same thing quite a lot. Say netlink.Handle has a Test method, and you want to call it inside showInts:

    func (h *MyHandle) showInts() {
        nh := (*netlink.Handle)(h) //cast required
        nh.Test()
    }
    

    I'd also change the varname from pid to nsh or something, because it's a NsHandle, and not a pid after all...


    What is a receiver argument?

    Because you wrote this:

    This is then a receiver argument (?) to a function that requires that handle,

    I get the impression you're not entirely clear on what a receiver argument is. Put simply, it's like a function argument, but instead of an argument that is just passed to a function, it's an argument that holds the object/value on which the function is called. Basically, it's the "instance" on which the function/method is called. Think of it as the this keyword in many OOP languages:

    func (h *MyHandle) showInts() {
        return
    }
    

    In something like C++ would be

    class MyHandle : Handle
    {
        public:
            void showInts(void) { return; } // replace h with this
    }
    

    There are significant differences, however:

    • The receiver argument can be a pointer, or a value - in case of a value receiver, the method cannot modify the receiver value
    • There's no such thing as private, public, or protected... at least not in the traditional OO way
    • ...

    There's quite a few differences, perhaps consider going through the golang tour. The stuff about go methods can be found here


    Other issues/weird things

    After looking at your code again, I'm really not sure whether this is correct:

    h.netlink.LinkList()
    

    In your main function, you call netlink.LinkList(). h is a *netlink.Handler. If you need to call the netlink.LinkList function, it's highly likely h.netlink.LinkList is not what you want to do. Instead, you should simply call netlink.LinkList().
    That's assuming you need to call the function in the first place.

    Given that you've already called it in the main function, why not pass it as an argument?

    //in main:
    ints, err := netlink.LinkList()
    //...
    h.showInts(ints)
    
    func (h *MyHandle)showInts(ll []netlink.Link) {
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘