方法功能中的Golang无效接收器类型

时间:2017-06-07 07:22:02

标签: pointers go casting type-conversion

我试图创建一个简单的包来将SSH命令发送到服务器。

我有以下代码:

type Connection *ssh.Client

func Connect(addr, user, password string) (conn Connection, err error) {
    sshConfig := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
        },
        HostKeyCallback: ssh.HostKeyCallback(func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }),
    }

    conn, err = ssh.Dial("tcp", addr, sshConfig)
    return
}

func (conn Connection) SendCommand() ([]byte, error) {
    session, err := (*ssh.Client)(conn).NewSession()
    // ...
}

我的问题出在两行func (conn Connection) SendCommand() ([]byte, error)session, err := (*ssh.Client)(conn).NewSession()上。

我无法从覆盖的*ssh.Client类型中弄清楚如何使用Connection的可用方法。

我知道我需要进行一些转换,并且使用ssh.Client(*conn).NewSession()会有效,但它会复制*ssh.Client的值,这似乎不是正确的方法。

使用自定义*ssh.Client类型时,如何访问type Connection *ssh.Client可用的方法?

3 个答案:

答案 0 :(得分:7)

您无法使用指针TypeSpec声明新类型。同时声明一个新类型专门用于删除整个方法集,因此您将不会使用*ssh.Client中的任何原始方法。

您想要的是通过在您自己的结构类型中嵌入*ssh.Client来使用合成:

type Connection struct {
    *ssh.Client
}

func Connect(addr, user, password string) (*Connection, error) {
    sshConfig := &ssh.ClientConfig{
        User: user,
        Auth: []ssh.AuthMethod{
            ssh.Password(password),
        },
        HostKeyCallback: ssh.HostKeyCallback(func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil }),
    }

    conn, err = ssh.Dial("tcp", addr, sshConfig)
    if err != nil {
        return nil, err
    }

    return &Connection{conn}, nil
}

func (conn *Connection) SendCommand() ([]byte, error) {
    session, err := conn.NewSession()
    // ...
}

答案 1 :(得分:1)

这是我能想到的最好的:

type Connection ssh.Client

func (conn *Connection) SendCommand() ([]byte, error) {
    (*ssh.Client)(conn).NewSession()

请注意,我已将类型更改为而不是是指针类型(但后来我为SendCommand创建了一个指针接收器)。我不确定是否有任何方法可以创建一个指针类型作为接收器的函数。

答案 2 :(得分:0)

另一个选择是使用类型别名来实现所需的行为。我试图做一些“聪明”的可读性:

type foo struct {
    i int
}

type foo_ptr = *foo

type foo_ptr_slice = []foo_ptr
type foo_ptr_map = map[string]foo_ptr
type foo_ptr_slice_map = map[string]foo_ptr_slice

func (r foo_ptr) dump() {
    fmt.Printf("%d\n", r.i)
}

func main() {
    // need a map of slice of pointers
    var m foo_ptr_map

    m = make(foo_ptr_map, 0)

    m["test"] = &foo{i: 1}

    var m2 foo_ptr_slice_map

    m2 = make(foo_ptr_slice_map, 0)
    m2["test"] = make(foo_ptr_slice, 0, 10)

    m2["test"] = append(m2["test"], &foo{i: 2})

    fmt.Printf("%d\n", m["test"].i)
    fmt.Printf("%d\n", m2["test"][0].i)
    m["test"].dump()
}

我承认类型别名是用于大规模重构的,但是出于可读性考虑,这似乎是一个很好的用途。