为什么要有函数?
这个问题咋一看,有点SB,函数肯定是写来用的啊,但是我不可以一步一步的执行我的步骤实现功能吗?可以,但是一方面会造成代码冗余,工作量大,另一方面不美观简洁。函数在我看来就是把经常需要使用的功能提炼出来,封装成一个函数,供后续反复调用。反应了一种特性:可复用性。
方法又是什么东东?
说到方法,得提一下Go语言中的struct结构体,struct结构体其实就是一种对象,方法其实是和和某个struct绑定的函数。类比Python就是class类中封装的函数。实际中的应用就是,你实例化一个struct之后,与struct绑定的方法你都可以使用。我的理解是按照对象struct进一步提炼了函数,这部分函数称为方法method。
接口?
A:你写Go也有两天了,接口应该写了不少吧?
B:接口?
接口interface也是一个对象,我之前对此非常不理解,最近突然有点明白这玩意儿了。接口也是一个对象,但是这个对象不是一个像struct结构体很形象化的对象,它是一个抽象的对象。前文不是提到了方法么。不同的struct也可以有类似的功能,比如电脑和手机都可以实现网上冲浪功能,前提都是:1.有电 2.网络通。对于公共的功能(上网)就可以封装成一个接口,实现这个接口的实例就可以调用这个接口下的方法method。实际就是进一步提炼去重了之前的方法。接口类型变量能够存储所有实现了该接口的实例。
type tester interface{
method1(入参)(返回)
method2(入参)(返回)
}
type struct1 struct{}
type struct2 struct{}
func(s1 *struct1) method1(入参)(返回){}
func(s2 *struct2) method1(入参)(返回){}
func(s1 *struct1) method2(入参)(返回){}
func(s2 *struct2) method2(入参)(返回){}
func main(){
var x tester
s1 := struct1{} //实例化
s2 := struct1{} //实例化
x = &s1
x.method1(入参)
x.method2(入参)
x = &s2
x.method1(入参)
x.method2(入参)
总结
可复用的功能可以通过函数进行封装。某些对象有功能,可以通过函数绑定struct生成方法method。有些对象有相同的功能(函数),这部分又可以提炼出生成interface接口。总之:持续提炼汇总分类!
附:
GO实现ssh远程对服务器进行操作:1.连接 2.执行命令 3.查看目录文件列表 4.上传下载文件
common
package common
import (
"bytes"
"fmt"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
"log"
"net"
"os"
"path"
"path/filepath"
)
type HostConn struct {
IP string
User string
Password string
Port int
}
func (hc *HostConn) SSHConn() (*ssh.Client, error) {
var (
auth []ssh.AuthMethod
addr string
clientConfig *ssh.ClientConfig
client *ssh.Client
//session *ssh.Session
err error
)
auth = make([]ssh.AuthMethod, 0)
auth = append(auth, ssh.Password(hc.Password))
hostKeyCallback := func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
}
clientConfig = &ssh.ClientConfig{User: hc.User, Auth: auth, HostKeyCallback: hostKeyCallback}
// create ssh
addr = fmt.Sprintf("%s:%d", hc.IP, hc.Port)
client, err = ssh.Dial("tcp", addr, clientConfig)
if err != nil {
return nil, err
}
// create session
//if session, err = client.NewSession(); err != nil {
// return nil, err
//}
return client, err
}
func (hc *HostConn) RemoteCMD(cmd string) {
var (
stdOut bytes.Buffer
stdErr bytes.Buffer
)
client, err := hc.SSHConn()
if err != nil {
fmt.Printf("ssh tcp connect failed,err:%v\n", err)
return
}
session, err := client.NewSession()
if err != nil {
fmt.Printf("cmd session create failed,err:%v\n", err)
return
}
defer session.Close()
session.Stdout = &stdOut
session.Stderr = &stdErr
err = session.Run(cmd)
if err != nil {
fmt.Printf("ssh cmd execute failed,err:%v\n", err)
return
}
fmt.Printf("标准输出是:%s", stdOut.String())
fmt.Printf("标准错误是:%s", stdErr.String())
}
func (hc *HostConn) SftpFileList(remotePath string) (s []string) {
client, err := hc.SSHConn()
if err != nil {
fmt.Printf("sftpfilelist create client failed,err:%v\n", err)
return nil
}
defer client.Close()
sftpClient, err := sftp.NewClient(client)
if err != nil {
fmt.Printf("sftpfilelist create sftp client failed,err:%v\n", err)
return nil
}
w := sftpClient.Walk(remotePath)
for w.Step() {
if w.Err() != nil {
continue
}
if !w.Stat().IsDir() {
a := path.Dir(w.Path())
if a != remotePath {
continue
}
s = append(s, w.Path())
}
}
return s
}
func (hc *HostConn) SftpDownLoad(localPath, remotePath string) {
client, err := hc.SSHConn()
if err != nil {
fmt.Printf("ssh tcp connect failed,err:%v\n", err)
return
}
sftpClient, err := sftp.NewClient(client)
if err != nil {
fmt.Printf("sftp client create failed,err:%v\n", err)
return
}
s := hc.SftpFileList(remotePath)
for _, k := range s {
filename := path.Base(k)
fmt.Println(filename)
localFile := filepath.Join(localPath, filename)
remoteFile := path.Join(remotePath, filename)
fmt.Println(localFile)
fmt.Println(remoteFile)
dsFile, err := os.Create(localFile)
if err != nil {
fmt.Printf("create local file failed,err:%v\n", err)
return
}
srcFile, err := sftpClient.Open(remoteFile)
if err != nil {
fmt.Printf("remote download file open remotefile failed,err:%v\n", err)
return
}
// defer func() {
// _ = dsFile.Close()
// _ = srcFile.Close()
// }()
_, err = srcFile.WriteTo(dsFile)
if err != nil {
fmt.Printf("data write failed,err:%v\n", err)
return
}
}
fmt.Println("文件下载完成!")
}
func (hc *HostConn) SftpUpload(localFilePath, localFileName, remoteFilePath, remoteFileName string) {
client, err := hc.SSHConn()
if err != nil {
log.Fatal(err)
return
}
defer client.Close()
SftpClient, err := sftp.NewClient(client)
if err != nil {
fmt.Printf("sftp client create failed,err:%v\n", err)
return
}
// 1.打开本地文件
// 2.创建服务器端文件
// 3.读取本地文件内容
// 4.读取内容写入远程服务器文件中
localFile := filepath.Join(localFilePath, localFileName)
remoteFile := path.Join(remoteFilePath, remoteFileName)
fmt.Println(localFile, "\n", remoteFile)
srcFile, err := os.Open(localFile)
if err != nil {
fmt.Printf("local file open failed,err:%v\n", err)
return
}
defer srcFile.Close()
dsFile, err := SftpClient.Create(remoteFile)
if err != nil {
fmt.Printf("create server file failed,err:%v\n", err)
panic(err)
}
defer dsFile.Close()
buf := make([]byte, 1024)
for {
n, _ := srcFile.Read(buf) // 将文件二进制内容写入buf中
if n == 0 {
break
}
dsFile.Write(buf)
}
fmt.Println("文件上传完毕!")
}
type Operator interface {
SSHConn() (*ssh.Client, error)
SftpDownLoad(localPath, remotePath string)
SftpUpload(localFilePath, localFileName, remoteFilePath, remoteFileName string)
SftpFileList(remotePath string) (s []string)
RemoteCMD(cmd string)
}
main.go
package main
import (
"RemoteAction/common"
"fmt"
)
func main() {
var x common.Operator
hostConn := common.HostConn{
User: "xxx",
IP: "xxxxx",
Password: "xxxxx",
Port: 22,
}
x = &hostConn
List := x.SftpFileList("/xxx/xx/xxx")
for _, k := range List {
fmt.Println(k)
}
x.SftpDownLoad("C:\\Users\\Administrator\\Desktop\\test", "/xx/xxxx/xxxx")
x.RemoteCMD("pwd")
x.SftpUpload("C:\\Users\\Administrator\\Desktop\\test", "xxx.txt", "/home/tidb/scripts", "test.txt")
}