大伟 Golang之路

Golang之路

下载

​ https://golang.google.cn/

​ https://golang.google.cn/dl/

​ 版本: go.1.18

安装

  1. GOROOT=D:\go1.18
  2. GOPATH=D:\gopath1.18
  3. GO111MODULE=on
  4. GOPROXY=https://goproxy.cn,direct

go mod 创建项目

  1. 新建目录: D:\gopath1.18\cdr
  2. 进入该目录下: …
  3. 初始化项目: go mod init cdr
  4. 下载包: go get github.com/gin-gonic/gin (现在完在这里:D:\gopath1.18\pkg\mod)
  5. 刷新包: go mod tidy
  6. Goland打开项目,import后根据红线提示编目index,再开始丝滑

gin

在线文档: https://www.itying.com/gin

我的专栏: https://www.itying.com/category-79-b0.html

官网: https://gin-gonic.com/zh-cn

gin基本结构

		r := gin.Default()
​		r.LoadHTMLGlob("templates/*")
​		r.GET("/",funcName)
1.GET 	 查
2.POST   增
3.PUT    改
4.DELETE 删
​		funcName(c *gin.Context){	
​			c.string(200,"aaaaaaaaaaa")}
1. c.string 返回字符串
2. c.json   返回json
3. c.jsonp  返回jsonp
4. c.xml    返回xml
5. c.html   返回网页,需要先加载模板:r.LoadHTMLGlob("templates/*") {{.变量名称}}
​		r.Run(":8080")

gin模板放在不同目录里面的配置方法

//引擎
r.LoadHTMLGlob("templates/**/*")
//模板起名
{{ define "aaa/a111.html" }}
{{ end }}
//路由方法使用模板
c.html(200,"aaa/a111.html",map[string]{})

gin模板嵌套

{{ template "aaa/a111.html" . }}

gin前端变量

{{ $a := .name }}

gin前端移除空格

{{- .name -}}

gin前端比较函数

eq lt gt le ge ne

gin前端条件判断

{{ if gt .score 80 }}
	优秀
{{ else if gt $score 60 }}
	及格
{{ else }}
	不及格
{{ end }}

gin前端range循环

<dl>
	{{ range $i,$v := .obj }}
		<li> {{ key为$i,值为$v }}  </li>
	{{ else }}
		a数组为空
	{{ end }}
</dl>

gin前端with解构

{{ with .atype }}
//然后a结构体就被赋值给.了

gin前端预定义函数

and , or , not , len , index

gin自定义函数

r.SetFuncMap(template.FuncMap{
    "formatDate":formatAsDate,   
})

gin静态文件服务

func main(){
    r := gin.Default()
    r.Static("/static","./static")
}
//把程序本目录下的s目录映给s路由

get传值给go

r.GET("/getValue",func(c *gin.Context){
    username := c.Query("username")
    age := c.Query("age")
    page := c.DefaultQuery("page","2")
    c.JSON(200,gin.H{
        "username" : username,
        "age" : age,
        "page" : page,
    })
})
//测试: http://1.1.1.1:8080/getValue?username=%E6%B1%AA%E4%BC%9F&age=99

post传值给go

//去到表单页
r.GET("/addUser",func(c *gin.Context){
    c.HTML(200,"default/addUser.html",map[string]interface{}{})
})
<!-- 表单提交给路由 -->
<form action="/doAddUser" method="post">
    用户名:<input type="text" name="username" /> <br><br>
    密 码:<input type="password" name="password" /> <br><br>
    <input type="submit" value="提交">
</form>
//执行路由post方法,golang获取表单值
r.POST("/doAddUser", func(c *gin.Context) {
	username := c.PostForm("username")
	password := c.PostForm("password")
	age := c.DefaultPostForm("age", "26")
	c.JSON(200, gin.H{
		"username": username,
		"password": password,
		"age":      age,
	})
})

get传值绑定到结构体

type UserInfo struct{
    Username string `json:"username" form:"username"`
    Password string `json:"password" form:"password"`
}
r.GET("/getUser",func(c *gin.Context){
    user := &UserInfo{}
    if err := c.ShouldBind(&user); err == nil {
        c.JSON(200,user)
    } else {
        c.JSON(200,gin.H{
            "ERR" : err.Error(),
        })
    }
})
// 测试 : http://1.1.1.1:8080/getUser?username=%E6%B1%AA%E4%BC%9F&password=0998*aa

post传值绑定到结构体

//去到表单页
r.GET("/addUser",func(c *gin.Context){
    c.HTML(200,"default/addUser.html",map[string]interface{}{})
})
<!-- 表单提交给路由 -->
<form action="/doAddUser2" method="post">
    用户名:<input type="text" name="username" /> <br><br>
    密 码:<input type="password" name="password" /> <br><br>
    <input type="submit" value="提交">
</form>
r.POST("/doAddUser2",func(c *gin.Context){
    user := &UserInfo{}
    if err := c.ShouldBind(&user); err == nil {
        c.JSON(200,user)
    } else {
        c.JSON(400,gin.H{
            "ERR" : err.Error(),
        })
    }
})

xml数据绑定到结构体

<?xml version="1.0" encoding="UTF-8"?>
<article>
	<content type="string">我是张三</content>
    <title type="string">张三</title>
</article>
type Article struct{
    Title string `json:"title" xml:"title"`
    Content string `json:"content" xml:"content"`
}
r.POST("/xml",func(c *gin.Context){
    article := &Article{}
    xmlSliceDate,_ = c.GetRawDate() //获取c.Request.Body字节流
    if err := xml.Unmarshal(xmlSliceDate,&article); err == nil {
        c.JSON(200,article)
    } else {
        c.JSON(400,gin.H{
            "ERR" : err.Error(),
        })
    }
})

gin动态路由

r.GET("/list/:cid", func(c *gin.Context){
	cid := c.Param("cid")
	c.String(200,"%v",cid)
})

gin加载css文件和jsp文件

参考网站: https://blog.51cto.com/dongweizhen/3606790

新增目录结构:

templates/statics/index.css
templates/statics/index.js

main.go内容

package main

import (
	"github.com/gin-gonic/gin"
	"html/template"
	"net/http"
)

func main() {
	//定义一个路由
	r := gin.Default()
	//加载静态文件
	r.Static("/dwz","templates/statics")
	//添加自定义函数,解析下面的“百度一下”html代码
	r.SetFuncMap(template.FuncMap{
		"safe": func(str string) template.HTML{
			return template.HTML(str)
		},
	})
	//模板解析
	r.LoadHTMLGlob("templates/**/*")
	//模板渲染
	r.GET("/posts", func(c *gin.Context) {
		c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{
			"title": "Posts index",
		})
	})
	r.GET("/users", func(c *gin.Context) {
		c.HTML(http.StatusOK, "users/index.tmpl", gin.H{
			"title": "<a href='https://www.baidu.com'>百度一下</a>",
		})
	})
	r.Run(":9090")
}

templates/statics/index.css内容

body {
    background-color: cadetblue;
}

templates/statics/index.js内容

alert(123);

templates/users/index.tmpl内容

{{define "users/index.tmpl"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/dwz/index.css">
    <title>Title</title>
</head>
<body>
{{.title | safe}}
<script src="/dwz/index.js"></script>
</body>
</html>
{{end}}

运行程序:

go run main.go

浏览器访问:

登录后复制

http://ip:9090/users

gin上传单文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2>演示文件上传</h2>
    <form action="/upload" method="post" enctype="multipart/form-data">
        用户名:<input type="text" name="username" placeholder="用户名" />
        <br><br>
        头像:<input type="file" name="face" />
        <br><br>
        <input type="submit" value="提交" />
    </form>
</body>
</html>
package main

import (
	"fmt"
	"log"

	"github.com/gin-gonic/gin"
)

func main() {
	r := gin.Default()
	r.LoadHTMLGlob("templates/*")

	//上传操作页
	//设置内存限制(默认是32M),这里设置为8M
	r.MaxMultipartMemory = 8 << 20 //8M
	fmt.Println(r.MaxMultipartMemory)
	r.POST("/upload", func(c *gin.Context) {
		file, err := c.FormFile("face")
		if err != nil {
			fmt.Println("读取表单失败")
			return
		}
		log.Println(file.Filename)
		path := `D:\go_ftp_dir`
		pathFile := path + "/" + file.Filename
		c.SaveUploadedFile(file, pathFile)
		c.String(200, fmt.Sprintf("'%s' uploaded!", file.Filename))
	})

	//上传接口页
	r.GET("/upload", func(ctx *gin.Context) {
		ctx.HTML(200, "upload.html", gin.H{})
	})

	r.Run(":8080")
}

crul 命令 也可以发送POST请求

curl -X POST http://localhost:8080/upload \
  -F "file=@/tmp/aaa.zip" \
  -H "Content-Type: multipart/form-data"

gin上传和下载

​ 批量上传

httpRouter.POST("/upload", func(ctx *gin.Context) {
		forms, err := ctx.MultipartForm()
		if err != nil {
			fmt.Println("error", err)
		}
		files := forms.File["fileName"]
		for _, v := range files {
			if err := ctx.SaveUploadedFile(v, fmt.Sprintf("%s%s", "./file/", v.Filename)); err != nil {
				fmt.Println("保存文件失败")
			}
		}
	})

​ 其实下载文件,通过http的get请求就行了,回去ctx.file()。

httpRouter.GET("/download", func(ctx *gin.Context) {
		filePath := ctx.Query("url")
		//打开文件
		file, err := os.Open("./" + filePath)
		if err != nil {
			fmt.Println("打开文件错误", err)
		}
		defer file.Close()

		//获取文件的名称
		fileName := path.Base(filePath)
		ctx.Header("Content-Type", "application/octet-stream")
		ctx.Header("Content-Disposition", "attachment; url="+fileName)
		ctx.Header("Content-Transfer-Encoding", "binary")
		ctx.Header("Cache-Control", "no-cache")

		ctx.File("./" + filePath)
	})

自恢复集群启动命令oninitdb的设计与实现 之golang知识点

go执行os系统命令

参考网站: https://zhuanlan.zhihu.com/p/296409942

package main

import (
    "bytes"
    "fmt"
    "log"
    "os/exec"
)

func main() {
    cmd := exec.Command("ls", "-l", "/var/log/*.log")
    var stdout, stderr bytes.Buffer
    cmd.Stdout = &stdout  // 标准输出
    cmd.Stderr = &stderr  // 标准错误
    err := cmd.Run()
    outStr, errStr := stdout.String(), stderr.String()
    fmt.Printf("out:\n%s\nerr:\n%s\n", outStr, errStr)
    if err != nil {
        log.Fatalf("cmd.Run() failed with %s\n", err)
    }
}

go发送get请求并解析网页的BodyString数据

参考网站:https://cloud.tencent.com/developer/article/1849807

func main(){
	//主addrss
	fmt.Println("远程添加")
	u := "http://" + zhuip + ":" + zhuport + "/addrss?my=" + my
	fmt.Println(u)
	response, err := http.Get(u)
	if err != nil {
		fmt.Println("http.Get addrss 时遇到异常")
	}
	buf, _ := ioutil.ReadAll(response.Body)
	s := string(buf)
	if s == "run addrss ok" {
		fmt.Println("run addrss ok")
	} else {
		fmt.Println("run addrss err")
	}
}

go返送get请求并解析网页BodyJSON数据到结构体

知识点:

  1. ioutil.ReadAll(response.Body) 读取所有Body数据
  2. json.Unmarshal(buf, &infoList[i]) 使用一个结构体地址解析json字符串
type Info struct {
	Servername string `JSON:"servername"`
	Mode       string `JSON:"mode"`
	Running    string `JSON:"running"`
}

var infoList [3]Info

func info() {
	//查看db节点infof
	fmt.Println("查看集群")
	for i, n := range webList {
		response, err := http.Get("http://" + n.ip + ":" + n.port + "/info")
		if err != nil {
			fmt.Println("info API 未正常提供服务,Docker可能已经异常。")
			continue
		}
		buf, _ := ioutil.ReadAll(response.Body)
		json.Unmarshal(buf, &infoList[i])
		fmt.Println(infoList[i])
	}
}

golang使用sftp和ssh

参考网站: https://www.programminghunter.com/article/35971402517/

sftp.go

package sshclient

import (
	"fmt"
	"log"
	"net"
	"os"
	"path"
	"time"

	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
)

func connect(user, password, host string, port int) (*sftp.Client, error) {
	var (
		auth         []ssh.AuthMethod
		addr         string
		clientConfig *ssh.ClientConfig
		sshClient    *ssh.Client
		sftpClient   *sftp.Client
		err          error
	)
	// get auth method
	auth = make([]ssh.AuthMethod, 0)
	auth = append(auth, ssh.Password(password))
	hostKeyCallbk := func(hostname string, remote net.Addr, key ssh.PublicKey) error {
		return nil
	}

	clientConfig = &ssh.ClientConfig{
		User:            user,
		Auth:            auth,
		Timeout:         1 * time.Second,
		HostKeyCallback: hostKeyCallbk,
	}

	// connet to ssh
	addr = fmt.Sprintf("%s:%d", host, port)

	if sshClient, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
		return nil, err
	}

	// create sftp client
	if sftpClient, err = sftp.NewClient(sshClient); err != nil {
		return nil, err
	}

	return sftpClient, nil
}

//发送文件
func SftpPut(user, password, host, fileName string) {
	var (
		err        error
		sftpClient *sftp.Client
	)

	// 这里换成实际的 SSH 连接的 用户名,密码,主机名或IP,SSH端口
	sftpClient, err = connect(user, password, host, 22)
	if err != nil {
		log.Fatal(err)
	}
	defer sftpClient.Close()

	// 用来测试的本地文件路径 和 远程机器上的文件夹
	var localFilePath = fileName
	var remoteDir = "/tmp/"
	srcFile, err := os.Open(localFilePath)
	if err != nil {
		log.Fatal(err)
	}
	defer srcFile.Close()

	var remoteFileName = path.Base(localFilePath)
	dstFile, err := sftpClient.Create(path.Join(remoteDir, remoteFileName))
	if err != nil {
		log.Fatal(err)
	}
	defer dstFile.Close()

	buf := make([]byte, 1024)
	for {
		n, _ := srcFile.Read(buf)
		if n == 0 {
			break
		}
		dstFile.Write(buf[:n])
	}

	fmt.Println("copy file to remote server finished!")
}

//下载文件
func SftpGet(user, password, host, fileName string) {

	var (
		err        error
		sftpClient *sftp.Client
	)

	// 这里换成实际的 SSH 连接的 用户名,密码,主机名或IP,SSH端口
	sftpClient, err = connect(user, password, host, 22)
	if err != nil {
		log.Fatal(err)
	}
	defer sftpClient.Close()

	// 用来测试的远程文件路径 和 本地文件夹
	var remoteFilePath = "/tmp/" + fileName
	var localDir = "lib/sshclient/sftpput/"

	srcFile, err := sftpClient.Open(remoteFilePath)
	if err != nil {
		log.Fatal(err)
	}
	defer srcFile.Close()

	var localFileName = path.Base(remoteFilePath)
	dstFile, err := os.Create(path.Join(localDir, localFileName))
	if err != nil {
		log.Fatal(err)
	}
	defer dstFile.Close()

	if _, err = srcFile.WriteTo(dstFile); err != nil {
		log.Fatal(err)
	}

	fmt.Println("copy file from remote server finished!")
}

sshclient.go

package sshclient

/*
go 1.14:
mkdir -p $GOPATH/src/golang.org/x/
cd $GOPATH/src/golang.org/x/
git clone https://github.com/golang/crypto.git

go 1.18
go get golang.org/x/crypto/ssh
*/

import (
	"bytes"
	"fmt"
	"net"
	"strings"
	"time"

	"golang.org/x/crypto/ssh"
)

// SSHConnect ssh连接
func SSHConnect(user, password, host string, port int) (*ssh.Client, *ssh.Session, error) {
	var (
		auth         []ssh.AuthMethod
		addr         string
		clientConfig *ssh.ClientConfig
		client       *ssh.Client
		session      *ssh.Session
		err          error
	)
	// get auth method
	auth = make([]ssh.AuthMethod, 0)
	auth = append(auth, ssh.Password(password))

	hostKeyCallbk := func(hostname string, remote net.Addr, key ssh.PublicKey) error {
		return nil
	}

	clientConfig = &ssh.ClientConfig{
		User:            user,
		Auth:            auth,
		Timeout:         1 * time.Second,
		HostKeyCallback: hostKeyCallbk,
	}

	// connet to ssh
	addr = fmt.Sprintf("%s:%d", host, port)

	if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
		return nil, nil, err
	}

	// create session
	if session, err = client.NewSession(); err != nil {
		return client, nil, err
	}

	return client, session, nil
}

// RunSSHpiliang 执行ssh 批量登陆执行
func RunSSHpiliang(user, password, host, cmdshell string) string {
	var stdOut, stdErr bytes.Buffer
	client, session, err := SSHConnect(user, password, host, 22)
	if client != nil {
		defer client.Close()
	}
	if session != nil {
		defer session.Close()
	}
	if err != nil {
		//fmt.Println(err,"   wei----------------------------------------")
		if strings.Contains(err.Error(), "i/o timeout") {
			return "连接主机的22端口时出错"
		}
		if strings.Contains(err.Error(), "unable to authenticate") {
			return "密码或SSHKEY验证时出错"
		}
		return "登录主机时出错"
	}
	session.Stdout = &stdOut
	session.Stderr = &stdErr
	if err := session.Run(cmdshell); err != nil {
		// fmt.Println(err.Error())
		// fmt.Println(stdOut.String())
		return "执行命令时出错!"
	}
	return stdOut.String()
}

golang 文件IO/目录IO/行IO/字节BUFIO

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func weiShuoMing() {
	// 删除覆盖   os.OpenFile("aaa", os.O_CREATE|os.O_RDWR, 6)
	// 行写文件   os.Openfile("aaa", os.O_CREATE|os.O_RDWD|os.O_APPEND,6)   f.WriteString("")

	// reader定义 reader,err := bufio.Reader(f)
	// 行读文件   os.Openfile("aaa",io.O_RDONLY,6) 或者用 os.Open("aaa")  f.ReadBytes('\n')
	// 偏移量     io.Seek(-12,io.SeekBeging) 还有Current和End

	// buf大小	 buf := make([]byte,4096)
	// 字节写文件  n,err:=reader.write(buf)
	// 字节读文件  n,err:=reader.read(buf)

	// 打开目录    os.Openfile("aaa",io.O_RDONLY,os.ModeDir)
	// 读取目录项   f.Readdir(-1) 返回[{Size() Name() IsDir() Modetime()}...]

	// https://studygolang.com/pkgdoc
	// https://www.bilibili.com/video/BV1TK4y1a7ex?from=search&seid=18159148304738299137
}

func main() {
	// 创建覆盖文件
	os.Create("aaa")
	// 打开文件aaa
	f, err := os.OpenFile("aaa", os.O_RDWR|os.O_APPEND, 6)
	if err != nil && err != io.EOF {
		fmt.Println("OpenFile打开文件aaa出错")
	}
	defer f.Close()
	// 写入5行数据
	f.WriteString("写入数据0001\n")
	f.WriteString("写入数据0002\n写入数据0003\n")
	f.WriteString("写入数据0004\n写入数据0005\n")
	// 移至文件开头
	f.Seek(0, io.SeekStart)
	// 读取第2,3行的数据
	reader := bufio.NewReader(f)
	i := 0
	for {
		hang, err := reader.ReadBytes('\n')
		if err == io.EOF {
			break
		} else {
			i++
		}
		if i == 2 || i == 3 {
			fmt.Print(string(hang))
		}
	}
	// buf读
	// 偏移15字节再读取第12,13,14,15,16,17,18,19个字节 (utf8一个汉字3个字节,换行\n为一个字节)
	f.Seek(15, io.SeekStart)
	buf := make([]byte, 8)
	f.Read(buf) //从f中读取一个buf空间的内容,给buf赋值。这个函数还返回n,err其中n是实际读取的切片长度。
	fmt.Printf("%q\n", buf)
	// buf写
	f.Seek(0, io.SeekEnd)
	f.Write(buf)
	f.Close()

	// 读取文件夹
	fd, err := os.OpenFile("D:/w_gopath/src/wei01/w_go_pg_tidb/05.go_wei", os.O_RDONLY, os.ModeDir)
	defer fd.Close()
	fdreader, err := fd.Readdir(-1)
	for zixiang, info := range fdreader {
		fmt.Println(zixiang, info.Name(), info.Size(), info.ModTime(), info.IsDir())
	}
}

// 大文件复制
func weicopy() {
	f4, err := os.Open("wei.mp3")
	if err != nil && err != io.EOF {
		fmt.Println("打开mp3失败")
	}
	defer f4.Close()

	f5, err := os.Create("wei_2.mp3")
	if err != nil && err != io.EOF {
		fmt.Println("打开mp3失败")
	}
	defer f5.Close()

	buf4k := make([]byte, 4096)
	for {
		n, err := f4.Read(buf4k)
		f5.Write(buf4k[:n])
		if err != nil && err != io.EOF {
			fmt.Println("读取文件出错")
			break
		}
		if n == 0 {
			fmt.Println("文件全部读完了")
			break
		}
		fmt.Println(n)
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值