我试图创建一个简单的包来将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
可用的方法?
答案 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()
}
我承认类型别名是用于大规模重构的,但是出于可读性考虑,这似乎是一个很好的用途。