Go语言学习笔记


(1)Go备份MySQL数据库至阿里云OSS

package main
import (
	"fmt"
	"os"
	"os/exec"
	"time"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
const (
	ossBucket          = "da**xn"
	ossPoint           = "http://oss-cn-chengdu.aliyuncs.com"
	ossAccessKeyId     = "LT*********oz"
	ossAccessKeySecret = "MI*********OT"
	originPath         = "/data/database/"
)
func main() {
	path := originPath
	file := "linzening-db-" + time.Now().Format("20060102150405") + ".sql.gz"
	cmd := exec.Command("/bin/sh", "-c", "/usr/bin/mysqldump --host 127.0.0.1 --port 3306 -uroot -pword dbname | gzip > "+path+file)
	err1 := cmd.Run()
	if err1 != nil {
		fmt.Println("error")
		os.Exit(-1)
	}
	fmt.Println("databasefile:" + path + file)

	// 创建OSSClient实例。
	client, err := oss.New(ossPoint, ossAccessKeyId, ossAccessKeySecret)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	// 获取存储空间。
	bucket, err := client.Bucket(ossBucket)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}

	// 上传本地文件。按月份文件夹保存到OSS
	osspath := "database-"+time.Now().Format("2006")+"/"+time.Now().Format("01")+"/"
	err = bucket.PutObjectFromFile(osspath+file, path+file)
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	fmt.Println("Upload Success.")
}
源代码

https://github.com/linzening/code/blob/main/go/oss-backup.go

(2)Go处理Nginx日志

打印日志状态码统计
package main
import (
    "fmt"
    "os"
    "io/ioutil"
    "strings"
    "strconv"
)
func main() {
    path := "i6.log"
    if len(os.Args) >=2 {
        path = os.Args[1]
    }
    fmt.Println("日志路径:",path)
    
    f, err := os.Open(path)
    if err != nil {
        fmt.Println("文件不存在")
        os.Exit(-1)
    }
    str,err := ioutil.ReadAll(f)
    if err != nil {
        fmt.Println("日志读取失败")
        os.Exit(-1)
    }
    strs := string(str)
    var countryCapitalMap map[int]int
    countryCapitalMap = make(map[int]int)
    lists := strings.Split(strs,"\n")
    for i := 0; i < len(lists);i++ {
        line := lists[i]
        row := strings.Split(line," ")
        if len(row) > 8 {
            b,_ := strconv.Atoi(row[8])
            if b >= 100 && b < 600 {
                countryCapitalMap[b] += 1
            }
        }
    }
    for country := range countryCapitalMap {
        fmt.Println(country, "状态码", countryCapitalMap[country])
    }
}

运行效果

[root@ecs go]# go run log.go /home/wwwlogs/access.log
日志路径: /home/wwwlogs/access.log
200 状态码 1532
404 状态码 1057
150 状态码 113
403 状态码 127
146 状态码 6
400 状态码 331
405 状态码 103
304 状态码 350
302 状态码 1
301 状态码 2
把日志统计输出到接口中
package main
import (
    "fmt"
    "os"
    "io/ioutil"
    "strings"
    "strconv"
    "net/http"
)
func getinfo() string {
    path := "i6.log"
    if len(os.Args) >=2 {
        path = os.Args[1]
    }
    fmt.Println("日志路径:",path)

    f, err := os.Open(path)
    if err != nil {
        fmt.Println("文件不存在")
        os.Exit(-1)
    }
    str,err := ioutil.ReadAll(f)
    if err != nil {
        fmt.Println("日志读取失败")
        os.Exit(-1)
    }
    strs := string(str)
    var countryCapitalMap map[int]int
    countryCapitalMap = make(map[int]int)
    var countryCapitalUrl map[string]int
    countryCapitalUrl = make(map[string]int)
    lists := strings.Split(strs,"\n")
    for i := 0; i < len(lists);i++ {
        line := lists[i]
        row := strings.Split(line," ")
        if len(row) > 8 {
            b,_ := strconv.Atoi(row[8])
            if b >= 100 && b < 600 {
                countryCapitalMap[b] += 1
            }
            if b != 200 && b != 304 && b != 206 && b != 302 {
                key := row[6]
                countryCapitalUrl[row[0]+","+strconv.Itoa(b)+","+key] += 1
            }
        }
    }
    strlog := "[{"
    for country := range countryCapitalMap {
        // fmt.Println(country, "状态码", countryCapitalMap[country])
        strlog += "\"" + strconv.Itoa(country) + "\":\""+ strconv.Itoa(countryCapitalMap[country])+"\","
    }
    // 去掉最后一个字符
    strlog = strlog[0:len(strlog)-1]
    strlog += "},{"
    for country := range countryCapitalUrl {
        // fmt.Println(countryCapitalUrl[country],country)
        country = strings.Replace(country,"\"","0",-1)
        country = strings.Replace(country,"\\","00",-1)
        strlog += "\""+country +"\":\""+ strconv.Itoa(countryCapitalUrl[country])+"\","
    }
    strlog = strlog[0:len(strlog)-1]
    return strlog+"}]"
}

type helloHandler struct{}

func (h *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    b := getinfo()
    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Write([]byte(b))
}

func main() {
    to := "web"
    if to == "web" {
        fmt.Println("服务器已启动:8000")
        http.Handle("/", &helloHandler{})
        http.ListenAndServe(":8000", nil)
    }else{
        fmt.Println("配置错误")
    }
}

生成二进制程序

go build flog.go

执行命令

nohup ./flog /home/wwwlogs/ayouleyangs.log &

(3)Go协程程序

package main

import (
    "fmt"
    "time"
)
//生产者
func Producer(queue chan<- int) {
    for i := 0; i < 10; i++ {
        queue <- i //写入
        fmt.Println(time.Now().Format("2006-01-02 15:04:05"),"create :", i)
        time.Sleep(1 * time.Second)
    }
}

//消费者
func Consumer(queue <-chan int) {
    for i := 0; i < 10; i++ {
        v := <-queue  // 读出
        fmt.Println(time.Now().Format("2006-01-02 15:04:05"),"receive:", v)
    }
}

func main() {
    queue := make(chan int, 88)
    go Producer(queue)
    go Consumer(queue)
    time.Sleep(12 * time.Second)
}
无限循环语句
//消费者
func Consumer(queue <-chan int) {
    for {
        v := <-queue
        fmt.Println(time.Now().Format("2006-01-02 15:04:05"),"receive:", v)
    }
}

(4)使用Go做一个HTTP服务器

2022年8月23日

package main
import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "os"
    "path"
    "strconv"
)
var dir string
var port int
var indexs []string
// 初始化参数
func init() {
    dir = path.Dir(os.Args[0])
    fmt.Println("本地地址:",dir)
    flag.IntVar(&port, "port", 80, "服务器端口")
    flag.Parse()
    indexs = []string{"index.html", "index.htm"}
}
func main() {
    http.HandleFunc("/", StaticServer)
    err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}
// 静态文件处理
func StaticServer(w http.ResponseWriter, req *http.Request) {
    file := dir + req.URL.Path
    fi, err := os.Stat(file)
    if os.IsNotExist(err) {
        http.NotFound(w, req)
        return
    }
    if err != nil {
        http.Error(w, err.Error(), 500)
        return
    }
    if fi.IsDir() {
        if req.URL.Path[len(req.URL.Path)-1] != '/' {
            http.Redirect(w, req, req.URL.Path+"/", 301)
            return
        }
        for _, index := range indexs {
            fi, err = os.Stat(file + index)
            if err != nil {
                continue
            }
            http.ServeFile(w, req, file+index)
            return
        }
        http.NotFound(w, req)
        return
    }
    http.ServeFile(w, req, file)
}

配置dir为本地目录,访问 http://127.0.0.1/ 即可

(5)又拍云存储制作文件浏览器-20230616

遍历又拍云的目录结构

func UpyunFileList(path string) (*[]*upyun.FileInfo,error) {
    var resultpush = make([]*upyun.FileInfo, 0)

    objsChan := make(chan *upyun.FileInfo, 10)
    go func() {
        up.List(&upyun.GetObjectsConfig{
            Path        : path,
            ObjectsChan : objsChan,
        })
    }()
    
    for obj := range objsChan {
        resultpush = append(resultpush, obj)
        if(obj.ContentType == "folder"){
            UpyunFileList(path + obj.Name + "/")
        }
    }
    
    MakePath(path,resultpush) //每个目录生成一个html文件
}

每一层目录生成一个html文件

func MakePath(path string,result []*upyun.FileInfo){
    vpath := strings.Replace(strings.Trim(path,"/"),"/","_",-1)
    rpath := vpath
    lpath := vpath
    if vpath == "" {
        rpath = "default"
    }else{
        lpath = lpath + "_"
    }
    liststr := "..." // html的头部部分

    if vpath != "" {
        // 返回上一级目录(需要计算上一级目录的情况)
        dpath := ""
        arr := strings.Split(strings.Trim(path,"/"),"/")
        if len(arr) >= 2 {
            arr = arr[:len(arr)-1]
            dpath = strings.Join(arr,"_")
        }else{
            dpath = "default"
        }
        liststr = liststr+"<tr><td><a class=\"octicon file-directory\" href=\""+dpath+".html\">..</a></td><td></td><td>"+"0"+"</td></tr>\n"
    }
    dhtml := ""
    fhtml := ""
    for obj := range result {
        if(result[obj].ContentType == "folder"){
            dhtml = dhtml+"<tr><td><a class=\"octicon file-directory\" href=\""+lpath+result[obj].Name+".html\">"+result[obj].Name+"</a></td><td>"+result[obj].Time.Format("2006-01-02 15:04:05")+"</td><td>"+strconv.FormatInt(result[obj].Size,10)+"</td></tr>\n"
        }else{
            fhtml = fhtml+"<tr><td><a class=\"octicon file\" href=\""+path + result[obj].Name+"\">"+result[obj].Name+"</a></td><td>"+result[obj].Time.Format("2006-01-02 15:04:05")+"</td><td>"+strconv.FormatInt(result[obj].Size,10)+"</td></tr>\n"
        }
    }
    liststr = liststr+dhtml+fhtml
    liststr = liststr+"</tbody></table></div></body></html>"
    file, err := os.Create("a/"+rpath+".html")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer file.Close()
    writer := bufio.NewWriter(file)
    _, err = writer.WriteString(liststr)
    if err != nil {
        fmt.Println(err)
        return
    }
    writer.Flush()
}

原始目录结构

direct
├── mysql
│   ├── Downloads
│   │   ├── MySQL-8.0
├── soft
│   ├── datebase
│   │   ├── phpmyadmin
│   ├── lib
│   │   ├── freetype
│   │   ├── lua
│   │   ├── openssl
│   ├── lnmp
│   ├── prober
│   ├── web
│   │   ├── libiconv
│   │   ├── libmcrypt
│   │   ├── mcrypt
│   │   ├── mhash
│   │   ├── nginx
│   │   ├── pcre
│   │   ├── php
│   │   │   ├── composer

生成的文件

default.html
mysql.html
mysql_Downloads.html
mysql_Downloads_MySQL-8.0.html
soft.html
soft_datebase.html
soft_datebase_phpmyadmin.html
soft_lib.html
soft_lib_freetype.html
soft_lib_lua.html
soft_lib_openssl.html
soft_lnmp.html
soft_prober.html
soft_web.html
soft_web_libiconv.html
soft_web_libmcrypt.html
soft_web_mcrypt.html
soft_web_mhash.html
soft_web_nginx.html
soft_web_pcre.html
soft_web_php.html
soft_web_php_composer.html

预览效果

预览效果

源代码:

https://github.com/linzening/code/blob/main/go/upyun-browser.go