golang.org/x/net/context --> github.com/golang/net/context
功能 | 操作 |
---|---|
删除当前行 | ⌘⌫ |
行注释 | ⌘/ |
块注释 | ⌥⌘/ |
函数使用提示 | ⌘P |
代码检查并提供快速修复 | ⌥⏎ |
import(
"fmt"
"math/rand"
…… ……
)
包名 | 介绍 | 作用 |
---|---|---|
fmt | 基本包 | 用于输入输出 |
math | 数学基本包 | |
表内容 | 表内容 | 代码内容 |
函数名 | 作用 |
---|---|
fmt.Println(String) | 输出指定字符串 |
func 函数名(参数1,参数2 数据类型) (返回数据1,返回数据2 数据类型){
…… ……
return
}
# example
func add(x , y int) (y , x) {
return
}
func 函数名(参数1,参数2 数据类型) (返回数据1的类型,返回数据2的类型){
…… ……
return 返回数据1 , 返回数据2
}
# example
func add(x , y int) (int , int) {
return x + y , x
}
函数返回值类型可以是func函数。
在函数中修改变量一般不影响全局的值,所以如果要改,必须传递一个指针进来,这个和C++相同
如果只返回一个返回数据,可以不写括号func 函数名(参数1,参数2 数据类型) 返回数据类型{……}
一个函数的返回值是一个函数。
原理:函数中回调一个子函数,可以理解为匿名函数,因为父函数被子函数依赖,所以其函数中定义的变量会一直存在内存中,每次调用函数后产生变化都是存在的。
可以把闭包理解为一个封装的环境中执行某个函数,每次定义一个变量存储这个环境,每次使用这个变量就是执行这个闭包中的子函数。
所以一般父函数中做的是环境定义,子函数做的是操作执行,如果定义两个变量,这两个变量中的值是相互不影响的。
对于执行的理解,可以是 f := function()
理解为执行父函数, f()
理解为执行子函数
func 函数名() func(参数类型) 返回值类型{
相关操作1
return func(参数 参数类型) 返回值类型{
相关操作2
return 返回值
}
}
# example
func function() func() {
a := 1
fmt.Println("只有第一次执行函数的时候才会触发")
return func(){
a ++
fmt.Println("每次执行这个函数都会执行,并且a变量值会一直存在")
}
}
# 定义一个变量存储这个函数
f := function()
f() // 这就是执行一次闭包
闭包可以有值输入或输出
func function() func(int) int{
a := 1
fmt.Println("只有第一次执行函数的时候才会触发")
return func(x int) int{
a += x
fmt.Println("每次执行这个函数吧输入的数加入")
return a
}
}
# 定义一个变量存储这个函数
f := function()
f(12) // 这就是执行一次闭包
定义的所有变量都要被使用 ,否则会报错
变量名1 变量类型1 , 变量名2 变量类型2
# 当变量类型相同的时候,等同如下
变量名1 , 变量名2 变量类型
# example
x int , y int <====> x , y int
var 变量名1 , 变量名2 变量类型
# example
var x , y bool
var 变量名1 , 变量名2 变量类型 = 值1 , 值2
# 系统自动获取变量类型
var 变量名1 , 变量名2 = 值1 , 值2
# example
var x , y int = 1 , 2
var x , y = 1 , 2
var (
x = 1
y = 2
)
下面是简洁写法,但是不能在函数外使用
变量1 , 变量2 := 值1 , 值2
# example
x , y := 1 , 2
变量类型 | 含义 | 默认值 | 代表符号 |
---|---|---|---|
bool | 代表ture 或者 false | false | %t |
string | 代表字符串 | (空) | %s |
int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr | 整数类型 | 0 | |
byte | uint8 的别名 | 0 | %d |
rune | int32 | 0 | %d |
float32 float64 | 浮点数 | 0 | %f |
complex64 complex128 | 虚数 | (0+0i) |
<< 所有二进制数向左移动n位
>> 所有二进制数向右移动n位
表达式 T(v)
将值 v
转换为类型 T
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
#string到int
int,err:=strconv.Atoi(string)
#string到int64
int64, err := strconv.ParseInt(string, 10, 64)
#int到string
string:=strconv.Itoa(int)
#int64到string
string:=strconv.FormatInt(int64,10)
test string
flag.StringVar(&test, "外部调用的名字", "默认值", "help提示文字")
flag.Parse()
// 然后test变量就会通过外部获取值
解决没有输入参数的异常
if mip == "Error" || cip == "Error" || vip == "Error" {
flag.Usage()
return
}
const 常量1 , 常量2 = 值1 , 值2
# 可以大批量复制
for i := 初始值 ; i < 最大值 ; i ++ {
…………
}
for i < 值 {
}
for {
}
会遍历整个数组中所有元素,然后每次都会把一个数据给变量2,而变量1会每次+1
for 变脸1,变量2 := range 数组名{
…… ……
}
变量1用来记录需要,可以不写
if 判断语句 {
} else {
}
判断语句中可以有变量定义,例如:
if err:=test();err != nil {
} else {
}
switch i {
case "值1":
……
case 函数名():
……
defalut:
……
}
最后执行下面这个函数,多个defer的时候,是采用堆栈逻辑,原理是先进后出执行
defer 函数()
其零值是 nil
*类型 指代某类型的指针
# example
var i *int
那么 i 的值就是 nil ;
在不赋值去情况下使用 *i 会报告异常
可以理解为一个自定义的数据类型
type 结构体名 struct{
变量1 类型
变量2 类型
}
# 使用方法
结构体.变量
结构体变量 := 结构体{值1,值2……}
指针名 := &结构体变量
# example
a := add{1,2}
b := &a
b.x 的值就是1
语法累死于闭包,函数的返回值是一个函数。
func (结构体变量 结构体类型) 方法名() 返回值类型{
return 指定类型的值
}
结构体变量 := 结构体…………
结构体变量.方法名()
# example
type Vertex struct {
X int
Y int
}
func (v *Vertex) Abs() float64 {
sum := v.X * v.X + v.Y * v.Y
return math.Sqrt(float64(sum))
}
func main() {
v := Vertex{4,3}
fmt.Println(v.Abs())
}
不光可以对自定义的结构体进行定义,也可以对数据类型,但是需要修改一个名字
type Vertex float
func (v Vertex) Abs() float64 {
return math.Sqrt(float64(v))
}
接口类型是由一组方法定义的集合。 接口类型的值可以存放实现这些方法的任何值。
但是不需要完成接口内方法的具体内容。
type 接口名 interface{
方法名() 方法返回值
}
其空值为 nil
# 基本格式
数组名 []数据类型
# make创建一个数组格式
数组名 := make([]数据类型 , len初始值 , cap初始值)
# 新添加元素
数组名 = append(数组名,值1,值2)
len默认值是0 , cap默认值是0
len代表slice实际元素的个数;
cap代表当前slice的容量
当len的长度不足够的时候,可以直接把数据存到容量中,如果达到初始设定容量,就会添加新加一个不比初始容量小的新容量,添加的容量无上限。
一般和make连用,这个不要求有数据
数组名 = make(map[键名类型]数组类型)
# 赋值的时候
数组名[任意键名] = 满足数组类型值
主要作用就是让数组的键名(下标),可以被自定义
如果有数据
数组名 = map[键名类型]数组类型{
键名1 : {值1 , 值2}
键名2 : {值1 , 值2}
}
delete(数组,键名)
变量名 , 存储状态变量 := 数组名[键名]
变量名 , 存储状态变量 = 数组名[键名]
if err := buildMha() ; err != nil {
// 程序继续,中断函数
log.Panic(err)
// 直接切断程序
log.Fatal(err)
}
err := ioutil.WriteFile("test.txt", []byte("Hi\n"), 0666)
if err != nil {
log.Fatal(err)
}
func myWrite(config string, word ...string) error {
for _, i := range word {
f, err := os.OpenFile(config, os.O_WRONLY, 0644)
if err != nil {
fmt.Println("cacheFileList.yml file create failed. err: " + err.Error())
return errors.New(i)
} else {
// 查找文件末尾的偏移量
n, _ := f.Seek(0, os.SEEK_END)
// 从末尾的偏移量开始写入内容
_, err = f.WriteAt([]byte(i+"\n"), n)
}
_ = f.Close()
if err != nil {
fmt.Println("cacheFileList.yml file writed failed. err: " + err.Error())
return errors.New(i)
}
}
return nil
}
func connect(user, password, host, key string, port int, cipherList []string) (*ssh.Session, error) {
var (
auth []ssh.AuthMethod
addr string
clientConfig *ssh.ClientConfig
client *ssh.Client
config ssh.Config
session *ssh.Session
err error
)
// get auth method , 用秘钥或者密码连接
auth = make([]ssh.AuthMethod, 0)
if key == "" {
auth = append(auth, ssh.Password(password))
} else {
pemBytes, err := ioutil.ReadFile(key)
if err != nil {
return nil, err
}
var signer ssh.Signer
if password == "" {
signer, err = ssh.ParsePrivateKey(pemBytes)
} else {
signer, err = ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte(password))
}
if err != nil {
return nil, err
}
auth = append(auth, ssh.PublicKeys(signer))
}
if len(cipherList) == 0 {
config = ssh.Config{
Ciphers: []string{"aes128-ctr", "aes192-ctr",
"aes256-ctr", "[email protected]", "arcfour256",
"arcfour128", "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc"},
}
} else {
config = ssh.Config{
Ciphers: cipherList,
}
}
clientConfig = &ssh.ClientConfig{
User: user,
Auth: auth,
Timeout: 30 * time.Second,
Config: config,
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
return nil
},
}
// ssh 连接
addr = fmt.Sprintf("%s:%d", host, port)
if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
return nil, err
}
// create session
if session, err = client.NewSession(); err != nil {
return nil, err
}
modes := ssh.TerminalModes{
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
return nil, err
}
return session, nil
}
const (
username = "root"
password = ""
key = "/root/.ssh/id_rsa"
port = 22
)
func sshDoShell(ip string, cmd string) error{
ciphers := []string{}
session, err := connect(username, password, ip, key, port, ciphers)
if err != nil {
fmt.Println("连接 ", ip, " 异常")
log.Fatal(err)
}
defer func() {
if err := session.Close(); err != nil {
// log etc
}
}()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
err = session.Run(cmd)
if err != nil{
return errors.New(err.Error())
}
return nil
}
func myCmd(bash string, shell ...string) error {
contentArray := make([]string, 0, 5)
cmd := exec.Command(bash, shell...)
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(cmd.Stderr, "error=>", err.Error())
}
_ = cmd.Start()
reader := bufio.NewReader(stdout)
contentArray = contentArray[0:0]
var index int
//实时循环读取输出流中的一行内容
for {
line, err2 := reader.ReadString('\n')
if err2 != nil || io.EOF == err2 {
break
}
fmt.Print(line)
index++
contentArray = append(contentArray, line)
}
err = cmd.Wait()
if err != nil {
fmt.Printf("Execute Shell %s: ", shell)
return errors.New("failed with error:"+err.Error())
}
return nil
}
var ListenSig = make(chan int)
type Route struct {
Name string
Method string
Pattern string
HandlerFunc http.HandlerFunc
}
type Routes []Route
// 记录访问记录
func Logger(inner http.Handler, name string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
inner.ServeHTTP(w, r)
File.WriteAccessLog(r.Method+"\t"+r.RequestURI+"\t"+name+"\t"+time.Since(start).String())
})
}
// 书写路由信息
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
var handler http.Handler
handler = route.HandlerFunc
handler = Logger(handler, route.Name)
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(handler)
}
return router
}
var routes = Routes{
// 获取指定日期的监控信息
Route{
"GetInfo",
"GET",
"/monitor/info",
ReturnMonitorInfo,
},
// 收集监控数据并保存处理
Route{
"MonitorCollect",
"POST",
"/monitor/collect",
PostMonitorInfo,
},
}
// 具体接口触发函数
func PostMonitorInfo(w http.ResponseWriter, r *http.Request) {
}
func ReturnMonitorInfo(w http.ResponseWriter, r *http.Request) {
}
// 启动api接口,port参数为暴露端口
func StartApi(port string) {
router := NewRouter()
File.WriteErrorLog(http.ListenAndServe(":"+port, router).Error())
ListenSig <- 0
}