英文:
Golang Invalid Receiver Type in Method Func
问题
我正在尝试创建一个简单的包来向服务器发送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()
。
我无法弄清楚如何在我的自定义Connection
类型中使用*ssh.Client
可用的方法。
我知道我需要进行一些转换,使用ssh.Client(*conn).NewSession()
可以工作,但它会复制*ssh.Client
的值,这似乎不是正确的方法。
在使用自定义的type Connection *ssh.Client
类型时,我应该怎么做才能访问*ssh.Client
可用的方法?
英文:
I'm trying to make a simple package to send SSH commands to a server.
I have the following code:
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()
// ...
}
My problem is on the two lines func (conn Connection) SendCommand() ([]byte, error)
and session, err := (*ssh.Client)(conn).NewSession()
.
I can't figure out how to use the methods available for *ssh.Client
from my overlaying Connection
type.
I understand that I need to do some conversion, and using ssh.Client(*conn).NewSession()
would work, but it copies the values of the *ssh.Client
which doesn't seem to be the right method.
What should do to access the methods available for a *ssh.Client
when working with my custom type Connection *ssh.Client
type?
答案1
得分: 43
你不能使用指针类型声明一个新的类型。此外,声明一个新类型的目的是为了移除整个方法集,所以你将无法使用*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()
// ...
}
英文:
You can't declare a new type with a pointer TypeSpec. Also declaring a new type is used specifically to remove the entire method set, so you won't have any of the original methods from the *ssh.Client
.
What you want is to use composition by embedding the *ssh.Client
in your own struct type:
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()
// ...
}
答案2
得分: 4
这是我能想到的最好的解决方案:
type Connection ssh.Client
func (conn *Connection) SendCommand() ([]byte, error) {
(*ssh.Client)(conn).NewSession()
请注意,我已经将类型更改为不是指针类型(但是我为SendCommand
创建了一个指针接收器)。我不确定是否有任何方法可以创建一个具有指针类型作为接收器的函数。
英文:
This is the best I can come up with:
type Connection ssh.Client
func (conn *Connection) SendCommand() ([]byte, error) {
(*ssh.Client)(conn).NewSession()
Note that I've changed the type to not be a pointer type (but then I've made a pointer receiver for SendCommand
). I'm not sure there's any way to create a function with a pointer type as a receiver.
答案3
得分: 1
另一种选择是使用类型别名来实现所需的行为。我试图做一些“巧妙”的事情以提高可读性:
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() {
// 需要一个指针切片的映射
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()
}
我承认类型别名用于大规模重构,但这似乎是为了提高可读性而非常好的用法。
英文:
Another option is to use type aliasing to achieve the desired behavior. I was trying to do something "clever" for readability:
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()
}
I acknowledge that type aliasing is used for large-scale refactoring but this seems like a very good use for readability sake.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论