Ale*_*ner 4 linux network-programming go netlink
目前正在使用vishvananda/netns
尝试从特定网络名称空间提取路由的包。
Handle
当我请求特定网络命名空间的“句柄”时,会返回一个已定义的结构。像这样:
func NewHandleAt(ns netns.NsHandle, nlFamilies ...int) (*Handle, error)
这是需要该句柄的函数的接收器参数(?),
func (h *Handle) LinkList() ([]Link, error)
我是新手,不知道如何将这些联系在一起。我被困住了:
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()
}
Run Code Online (Sandbox Code Playgroud)
在编写原始答案时,触及了很多内容,但没有任何清晰的结构,因此这里有一个更结构化的版本:
根据您实际询问的内容(即“如何将接收器函数/方法添加到导出类型”或“接收器函数到底是什么”),答案如下:
很简单,就像处理任何其他类型一样。事实上,你很接近。这不起作用:
func (h *Handler) showInts() {}
Run Code Online (Sandbox Code Playgroud)
因为您要向包中Handler
的类型添加一个方法。如果你有一个函数,那就是包。您正在尝试将其添加到类型中。在这种情况下,这将起作用:main
main
netlink.Handler
func (h *netlink.Handler) showInts(){}
Run Code Online (Sandbox Code Playgroud)
netlink.Handler
毕竟,该类型位于您的主包中...但是,这是行不通的。编译器会拒绝编译,告诉你:“Cannot Define new method on non-local type”。不过,通过创建一个新类型并在其中添加方法可以轻松缓解这一问题:
type MyHandler netlink.Handler
func (h *MyHandler) showInts(){}
Run Code Online (Sandbox Code Playgroud)
尽管如此,代码中的最后两行让我觉得是错误的。鉴于NewHandleAt
返回(*Handle, error)
, 并且netlink.Handle
是接收者参数,正确的方法是:
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
Run Code Online (Sandbox Code Playgroud)
事实上,您已将外部类型“包装”在自定义类型中,这确实意味着您会发现自己多次转换相同的东西。假设netlink.Handle
有一个Test
方法,并且您想在内部调用它showInts
:
func (h *MyHandle) showInts() {
nh := (*netlink.Handle)(h) //cast required
nh.Test()
}
Run Code Online (Sandbox Code Playgroud)
我还将 varname 从 更改为pid
或nsh
其他名称,因为它是 a NsHandle
,而不是 apid
毕竟......
因为你写了这个:
这是需要该句柄的函数的接收器参数(?),
我的印象是您并不完全清楚接收者参数是什么。简而言之,它就像一个函数参数,但它不是一个刚刚传递给函数的参数,而是一个保存调用该函数的对象/值的参数。基本上,它是调用函数/方法的“实例” 。将其视为this
许多 OOP 语言中的关键字:
func (h *MyHandle) showInts() {
return
}
Run Code Online (Sandbox Code Playgroud)
在像 C++ 这样的东西中
class MyHandle : Handle
{
public:
void showInts(void) { return; } // replace h with this
}
Run Code Online (Sandbox Code Playgroud)
然而,也存在显着差异:
有相当多的差异,也许可以考虑通过 golang 之旅。关于 go 方法的内容可以在这里找到
再次查看您的代码后,我真的不确定这是否正确:
h.netlink.LinkList()
Run Code Online (Sandbox Code Playgroud)
在您的main
函数中,您调用netlink.LinkList()
. h
是一个*netlink.Handler
. 如果您需要调用该netlink.LinkList
函数,那么它很可能不是h.netlink.LinkList
您想要做的。相反,您应该简单地调用.
假设您首先需要调用该函数。netlink.LinkList()
既然您已经在函数中调用了它main
,为什么不将它作为参数传递呢?
//in main:
ints, err := netlink.LinkList()
//...
h.showInts(ints)
func (h *MyHandle)showInts(ll []netlink.Link) {
}
Run Code Online (Sandbox Code Playgroud)