Go语言中函数,方法,接口之间的关系

为什么要有函数?

这个问题咋一看,有点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")
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值