Go

发布时间 2023-04-25 16:11:22作者: 李阿鸡

Go语言

Go语言介绍

​ 全称Golang,是Google公司2009年11月对外公布的一门编程语言
静态强类型(静态:类型固定 强类型:不同类型不允许直接运算)
属于 编译型语言 源代码编译成机器语言,由机器直接执行机器码即可执行。

python是解释型语言,想要编译成可执行文件需要借助于 pipinstaller

https://zhuanlan.zhihu.com/p/430490285

python代码防泄漏方案

1.启动起来后删除源代码
2.使用pipinstaller,打包成可执行文件
3. 做到docker镜像中,运行容器需要进行授权码校验。即-e PASSWORD

Go语言特性

​ 1. 跨平台的编译型语言

​ 2. 语法接近c语言

​ 3. 管道(channel),切片(slice),并发(routine)

​ 4. 支持面向对象和面向过程编程模式

Go语言发展

2015年8月19日 go1.5 —— 实现的架构变化,同时保留了和旧版本的兼容性,本次更新中移除了”最后残余的C代码”---》以后再写go不用c写了,用go写---》语言的自举
2018年8月24日 go1.11 —— modules和WebAssembly支持  go mod模式  包管理
最新 1.20版

Go语言应用程序

​ 像k8s,docker,七牛都是Go语言编写的

环境搭建

1.下载go的sdk(开发环境)

https://golang.google.cn/dl/
    下载msi文件

2.下载编辑器 goland ,vscode

https://www.jetbrains.com.cn/go/download/other.html

先安装环境在安装编辑器,一路下一步

hello world

package main // package 声明 这个go文件属于哪个包
import (
	"fmt" // fmt.Println 会自动导入这个 goland做的
	"time"
)

func main() {
	fmt.Println("hello world")
	time.Sleep(10 * time.Second)
}

// 编译代码成可执行文件,在哪个平台就默认编译成当前平台的

// 命令行执行go build 文件名.go 就可以生成可执行文件

变量名命名规范

​ Go语言中的函数名、变量名、常量名、类型名和包名等所有的命名,都遵循一个简单的命名规则

  1. 一个名字必须用字母开头或下划线开头,后面可以跟着任意数量的数字字母
  2. 大写字母与小写字母有不同的含义。
  3. 关键字和保留字不能作为变量名

25个关键字

break      default       func     interface   select
case       defer         go       map         struct
chan       else          goto     package     switch
const      fallthrough   if       range       type
continue   for           import   return      var

37个保留字

内置常量: true false iota nil
内置类型:  int int8 int16 int32 int64
          uint uint8 uint16 uint32 uint64 uintptr
          float32 float64 complex128 complex64
          bool byte rune string error
内置函数: make len cap new append copy close delete
          complex real imag
          panic recover

建议定义变量,函数名使用:用驼峰

go文件命名:建议用下划线

变量的定义和使用

package main

import "fmt"

// 变量定义
func main() {
	// 1.完整定义var关键字 变量名 变量类型 = 变量值
	//var name string = "lxj" // string  必须用双引号
	//var age int = 19        // 数字

	// 2. 类型推导,根据值自动推导出变量类型
	//var name = "lxj"
	//name = "pyy"      // 只能更改成同一类型

	// 3.简略声明 必须使用:= 不能分家
	//name := "lqz"

	// 4.一次性声明多个变量
	// 完整定义 1
	//var name, age, hobby string = "坤", "21", "唱跳rap打篮球"  // 问题是只能指定一个类型
	// 完整定义多个变量 2
	//var (
	//	name  string = "爱坤"
	//	age   int    = 19
	//	hobby string = "唱跳Rap打篮球"
	//)

	// 5.类型推导 1
	//var name, age, hobby = "坤", 19, "唱跳rap打篮球"
	// 方法  2
	//var (
	//	name  = "爱坤"
	//	age   = 19
	//	hobby = "唱跳Rap打篮球"
	//)

	// 6.简略声明
	//name, age, hobby := "坤", 19, "唱跳rap打篮球"

	// 7.完整定义和类型推导混合使用
	//var (
	//	name      = "坤"
	//	age   int = 19
	//	hobby     = "唱跳rap打篮球"
	//)

	// 8 变量名不能重复定义
	//var name = "坤"
	//var name = "lxj"  // 报错 重复定义
	//name := "lxj"     // 报错没有新变量在左侧

	// 9 变量可以先定义在赋值,必须使用完整定义反射
	//var name string // 默认值空字符串
	//var age int     // 默认值0
	//
	//age = 19               // 可以后面在赋值

	//fmt.Println(name, age) // 定义了变量必须用,不用会报错
	// 10,查看变量类型
	a := 19
	fmt.Printf("a的值是:%v,类型是:%T", a, a) // printf可以打印出变量的值和类型

}

变量类型

数字

# 整数有正负
int8    int16   int32	 int64
"rune 是 int32的别名"

# 正整数
uint8   uint16  uint(32位系统是32,64位系统是64)
"byte 是uint8的别名"

# 浮点型
float32   float64  # 小数后面范围不一样

# 复数类型
complex64  complex128
  • int8:-128 ~ 127
  • int16:-32768 ~ 32767
  • int32:-2147483648 ~ 2147483647
  • int64:-9223372036854775808 ~ 9223372036854775807

字符

# string 
双引号包裹不能换行, 反引号可以回车换行
"go 用单引号包裹字符,会返回对应的ASCII码"

布尔类型

true 
false

常量

定义常量

func main() {
	//1 .定义常量
	const name string = "lxj"
	const username = "nxm"
	println(name, username)
}

常量与变量的作用范围

在内部可以重新定义变量的

package main
var name string = "lxj"
func main() {
	// 内部没有用外部的
	//name := "pyy"   // 内部有优先用内部的
	println(name)
}

内置常量iota

想要使用必须用const 关键字,他的作用是自增

func main() {
	const (
		a = iota // 0
		b        // 1
		c        // 2
		d        // 3
	)
	println(a, b, c, d)
}

===================================================================
func main() {
	const (
		a = 10   // 10
		b = iota // 1   iota在哪一行 就从那一行开始自增
		c        // 2
		d        // 3
	)
	println(a, b, c, d)
}

iota 后续的行都会自增,不需要在+iota

函数

基础用法

普通函数
func main() {
	test()

}
func test() {
	fmt.Println("我是普通函数")
}

有参函数

func main() {
	test(1, "1")

}
// 必须指定参数的类型
func test(a int, b string) {
	fmt.Println(a, b)
}
===================================================================
func main() {
	test(1, 10, "ss")

}
// 多个参数相同类型可以简写
func test(a, c int, b string) {
	fmt.Println(a, b, c)
}

有返回值的有参函数
func main() {
	res := test(1, 10)
	fmt.Println(res)
}
// 需要在test(a, b int) 后面指定返回值的类型
func test(a, b int) int {
	return a + b
}
===================================================================
// 多个参数多个返回值
func main() {
	res, res1 := test(1, 10, "成功")
	fmt.Println(res, res1)
}

func test(a, b int, c string) (int, string) {
	return a + b, c
}

高级用法

同一个包下的变量函数只能定义一次,用了同样的名字会报错

匿名函数,一般定义在其他函数的内部

package main

import "fmt"

func main() {
	test()
}
func test() {
	func() {
		fmt.Println("我是内部的匿名函数")
	}() // 需要加括号调用,不然报错
}

定义变量接收函数,匿名函数带参数

package main

import "fmt"

func main() {
	test1()
}
func test() {
	//f := func() {
	//	fmt.Println("我是内部的匿名函数")
	//} // 报错需要指定f的类型
	var f func() = func() {
		fmt.Println("我是内部的匿名函数")
	}
	fmt.Printf("%T", f) // 打印出来是func() 类型,可以自定义
}

func test1() {
	var f func() = func() {
		fmt.Println("内层函数")
	}
	// func(a int) 也可以不写 函数的参数和返回值都是类型的一部分(如果写类型也要写参数)
	var f1 func(a int) = func(a int) {
		fmt.Println(a)
	}
	var f2 func(b int) int = func(b int) int {
		fmt.Println(b)
		return b + 10
	}

	var f3 func(b int) string = func(b int) string {
		fmt.Println(b)
		return "我是你爹"
	}
	fmt.Printf("%T\n", f)  // 打印出来是func()
	fmt.Printf("%T\n", f1) // 打印出来是func(int)
	fmt.Printf("%T\n", f2) // 打印出来是func(int) int
	fmt.Printf("%T\n", f3) // 打印出来是func(int) string
	f3(1)

}

可以简写:
f3  := func(b int) string {
		fmt.Println(b)
		return "我是你爹"
	}

函数作为返回值

func main() {
	res := test2()
	fmt.Printf("%T", res)
}

func test2() func() {
	return func() {
		fmt.Println("我是内层函数")
	}
}

调用函数返回闭包函数 (闭包函数内用到了外部作用域的变量)

func main() {
	res := test2()
	res()  // 取决于闭包函数有没有参数,有就要传
	fmt.Printf("%T", res)
}

func test2() func() {
	a := 10
	f := func() {
		fmt.Println(a)
	}
	return f
}