go实现并发文件传输,断点续传

go实现并发文件传输,断点续传

1: 概述

很多文件基本都是多协程下载文件要么就只有单协程的断点续传,这里给大家写一个支持有进度条的多协程下载文件,也支持断点续传

2: 使用示例代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package main

import (
	"fmt"
	"io"
	"os"
	"regexp"
	"strconv"
	"sync"

	"github.com/qianlnk/pgbar"
)

/**
* 需求:
1. 多协程并发下载文件
2. 断点续连
**/
func main() {
	//获取要下载文件
	DownloadFileName := "./Charles.4.5.6.zip"
	//copy的文件
	copyFileName := "./test.zip"
	storgeFileName := "./downloadRate.txt"
	//打开文件
	sfile, err := os.Open(DownloadFileName)
	if err != nil {
		panic(err)
	}
	defer sfile.Close()
	//获取文件大小
	info, _ := sfile.Stat()
	downloadSize := info.Size()
	var scount int64 = 1
	if downloadSize%5 == 0 {
		scount *= 5
	} else {
		scount *= 10
	}
	//分给每个协程的大小
	si := downloadSize / scount
	fmt.Printf("文件总大小:%v, 分片数:%v,每个分片大小:%v\n", downloadSize, scount, si)
	//open copy file
	copyFile, err := os.OpenFile(copyFileName, os.O_CREATE|os.O_WRONLY, os.ModePerm)
	if err != nil {
		panic(err)
	}
	storgeFile, err := os.OpenFile(storgeFileName, os.O_CREATE|os.O_RDWR, os.ModePerm)
	if err != nil {
		panic(err)
	}
	defer copyFile.Close()

	var currentIndex int64 = 0
	wg := sync.WaitGroup{}
	fmt.Println("文件下载进度条...")
	pgb := pgbar.New("")
	for ; currentIndex < scount; currentIndex++ {
		wg.Add(1)
		go func(current int64) {
			p := pgb.NewBar(fmt.Sprintf("%02d", (current+1))+"st", int(si))
			p.SetSpeedSection(900, 100)
			b := make([]byte, 10240)
			bs := make([]byte, 16)
			currentIndex, _ := storgeFile.ReadAt(bs, current*16)
			//取出所有整数
			reg := regexp.MustCompile(`\d+`)
			countStr := reg.FindString(string(bs[:currentIndex]))
			total, _ := strconv.ParseInt(countStr, 10, 0)
			progressBar := 1
			for {
				if total >= si {
					wg.Done()
					break
				}
				//从指定位置开始读
				n, err := sfile.ReadAt(b, current*si+total)
				if err == io.EOF {
					wg.Done()
					break
				}
				//从指定位置开始写
				copyFile.WriteAt(b, current*si+total)
				storgeFile.WriteAt([]byte(strconv.FormatInt(total, 10)+" "), current*16)
				total += int64(n)
				if total >= si/10*int64(progressBar) {
					progressBar += 1
					p.Add(int(si / 10))
				}
			}

		}(currentIndex)
	}
	wg.Wait()
	storgeFile.Close()
	os.Remove(storgeFileName)
	fmt.Printf("\n下载完成...\n")
}

goplugin功能

Go Plugin插件(so动态库)

1: 官方实现

  • golang 1.8 及以上版本提供了一个创建共享库(shared object)的新工具,称为 Plugins。
  • 目前 Plugins 仅在 Linux、FreeBSD 和 macOS 上受支持,且只支持 golang 调用。

2: 使用示例,定义一个 plugin.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

import (
	"log"
)

func init() {
	log.Println("plugin init")
}

type SayHello struct {
}

func (s *SayHello) CallMe(name string) string {
	log.Println("hello ", name)
	return "I am plugin"
}

// SayHelloPlugin 导出变量
var SayHelloPlugin SayHello

/*
使用 -buildmode=plugin 模式编译出 plugin.so 共享库
go build -o plugin.so -buildmode=plugin plugin.go

*/
  • 使用 -buildmode=plugin 模式编译出 plugin.so 共享库;
  • go build -o plugin.so -buildmode=plugin plugin.go

3: main.go 中调用插件(共享库)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
	"log"
	"plugin"
)

type CustomPlugin interface {
	CallMe(name string) string
}

func main() {
	// 打开插件(并发安全)
	p, err := plugin.Open("plugin.so")
	if err != nil {
		panic(err)
	}
	// 在插件中搜索可导出的变量或函数
	sayHelloPlugin, err := p.Lookup("SayHelloPlugin")
	if err != nil {
		panic(err)
	}
	// 断言插件类型
	if sayHello, ok := sayHelloPlugin.(CustomPlugin); ok {
		log.Println(sayHello.CallMe("togettoyou"))
	}
}

// go run main.go
// # 输出
// 2021/07/28 17:07:21 plugin init
// 2021/07/28 17:07:21 hello  togettoyou
// 2021/07/28 17:07:21 I am plugin

4:定义一个插件共享库总结:

1
2
3
4
5
6
7
package 包名需要定义为 main

必须有可导出的变量或函数

不需要 main 函数

插件加载时会先执行 init 函数

5:Traefik Yaegi 实现

  • yaegi 是一个 go 解释器;
  • https://github.com/traefik/yaegi
  • Yaegi 运行在 Go 运行时之上,可以直接作为嵌入式解释器,或使用交互式 shell ,解释运行 Go 代码

5.1 代码结构

  • 这里有个注意点,Yaegi 的插件需要放在 src 目录下;
1
2
3
4
5
6
7
8
9
  go.mod
  go.sum
  main.go

└─plugin
    └─src
        └─hello
                go.mod
                hello.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package hello

import (
 "fmt"
)

func init() {
 fmt.Println("hello plugin init")
}

func CallMe(msg string) string {
 fmt.Println(msg)
 return "I am plugin"
}

5.3 main.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
 "fmt"
 "github.com/traefik/yaegi/interp"
 "github.com/traefik/yaegi/stdlib"
)

func main() {
 // 初始化解释器
 i := interp.New(interp.Options{GoPath: "./plugin/"})

 // 插件需要使用标准库
 if err := i.Use(stdlib.Symbols); err != nil {
  panic(err)
 }

 // 导入 hello 包
 if _, err := i.Eval(`import "hello"`); err != nil {
  panic(err)
 }

 // 调用 hello.CallMe
 v, err := i.Eval("hello.CallMe")
 if err != nil {
  panic(err)
 }
 callMe := v.Interface().(func(string) string)
 fmt.Println(callMe("togettoyou"))
}
go run main.go

# 输出
hello plugin init
togettoyou
I am plugin

0091-python好用的脚本

1:图片处理

1.1 截图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#! /usr/bin/env python3
# encoding=utf-8


from mss import mss

import PIL.ImageGrab


def screenshot_1():
    """python 截屏方法1
    mss
    """
    with mss() as screenshot:
        screenshot.shot(output="scr.png")


def screenshot_2():
    """python 截屏方法2
    pillow
    """
    scr = PIL.ImageGrab.grab()
    scr.save("scr.png")


def main():
    print("this is main function")
    # screenshot_1()
    screenshot_2()


if __name__ == "__main__":
    main()
    print('__name__ value:', __name__)

1.2 将图像转换为素描图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 图像转换
import cv2
# 读取图片
img = cv2.imread("img.jpg")
# 灰度
grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
invert = cv2.bitwise_not(grey)
# 高斯滤波
blur_img = cv2.GaussianBlur(invert, (7, 7), 0)
inverse_blur = cv2.bitwise_not(blur_img)
sketch_img = cv2.divide(grey, inverse_blur, scale=256.0)
# 保存
cv2.imwrite('sketch.jpg', sketch_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

2:

3:

4:

5:

6:

7:

8:

9:

01-可观测性

云原生可观测性

1: OPLG 是什么

随着云原生架构的兴起,可观测的边界与分工被重新定义,传统的容器/应用/业务分层监控边界被打破,Dev、Ops、Sec 的分工逐渐模糊。大家意识到 IT 系统作为一个有机的整体,对 IT 系统状态的监测与诊断也需要一体化的方案。经过近几年的摸索与实践,基于 OPLG 的新一代云原生可观测体系,逐步成为了社区与企业的热门选择。

001-linux安装多版本python环境

1:简介

使用源码安装多个版本 python 环境,对系统原有 py 不影响

2:Linux 安装多个版本 python

2.1 下载 python 安装包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ---------- python3.8 源码安装 --------------
// (1) 创建安装目录
mkdir -p /usr/local/python/python3.8
cd /usr/local/python/python3.8
// (2) 下载源码包
sudo wget  https://registry.npmmirror.com/-/binary/python/3.8.13/Python-3.8.13.tgz
tar -zxvf Python-3.8.13.tgz
cd Python-3.8.13
// (3) 配置要安装的目录
./configure prefix=/usr/local/python/python3.8 --enable-optimizations
// (4) 编译源码
sudo make -j8
// (5) make altinstall与make install的区别,altinstall skips creating the python link and the manual pages links
// https://blog.csdn.net/andylauren/article/details/108363030
sudo make altinstall



// python3.10
mkdir -p /usr/local/python/python3.10
cd /usr/local/python/python3.10
sudo wget https://registry.npmmirror.com/-/binary/python/3.10.6/Python-3.10.6.tgz

2.2 update-alternative 管理多版本 python

update-alternatives 命令用于处理 linux 系统中软件版本的切换

01-001-linux安装多版本python环境

1:简介

使用源码安装多个版本 python 环境,对系统原有 py 不影响

2:Linux 安装多个版本 python

2.1 下载 python 安装包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ---------- python3.8 源码安装 --------------
// (1) 创建安装目录
mkdir -p /usr/local/python/python3.8
cd /usr/local/python/python3.8
// (2) 下载源码包
sudo wget  https://registry.npmmirror.com/-/binary/python/3.8.13/Python-3.8.13.tgz
tar -zxvf Python-3.8.13.tgz
cd Python-3.8.13
// (3) 配置要安装的目录
./configure prefix=/usr/local/python/python3.8 --enable-optimizations
// (4) 编译源码
sudo make -j8
// (5) make altinstall与make install的区别,altinstall skips creating the python link and the manual pages links
// https://blog.csdn.net/andylauren/article/details/108363030
sudo make altinstall



// python3.10
mkdir -p /usr/local/python/python3.10
cd /usr/local/python/python3.10
sudo wget https://registry.npmmirror.com/-/binary/python/3.10.6/Python-3.10.6.tgz

2.2 update-alternative 管理多版本 python

update-alternatives 命令用于处理 linux 系统中软件版本的切换

01-kafka

消息队列Kafka

1: Introduction

2: Arch 架构

3: 可视化 tools

1
2
//  kafka-map
https://github.com/dushixiang/kafka-map

01-有趣项目记录

有趣项目记录

1: 工具类

2: 好玩类

2.1 自动发送暖心邮件

1
https://github.com/Vincedream/NodeMail

2.2 土味情话生成器

1
https://github.com/zerosoul/honeyed-words-generator

3: 文件传输

1
2
3
// tl-rtc-file
// 用webrt在web端传输文件,支持传输超大文件, 分片传输,跨终端,不限平台,方便使用,内网不限速,支持私有部署
https://github.com/iamtsm/tl-rtc-file

4: 分布式文件系统

1
2
seaweedfs
https://github.com/seaweedfs/seaweedfs

5: 工具类

  • ctop