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/ 即可