1.Go语言
1.命令
1.1 查看版本号
go version
1.2 查看安装信息
go env
2.资料
2.1 官方文档
https://studygolang.com/pkgdoc
2.2 md 语法
https://www.appinn.com/markdown/
2.3 go环境的安装
官网安装包下载地址为:https://golang.org/dl/
如果打不开可以使用这个地址:https://golang.google.cn/dl/
2.4注意事项
1.把liteIDEA放到go安装的根目录下
2.ctrl+F7 编译运行
3.helloWorld函数
package main
import "fmt"
func main() {
fmt.Println("hello go")
}
2.语法
2.1
2.1声明变量
var a int
fmt.Println("a = ",a)
2.1.1 声明变量特殊语法(常用)
var a int = 40
a = 30
fmt.Println("a = ", a)
//c :=30 == var a int = 40 常用
c := 30
fmt.Printf("param type is %T\n", c)
2.1.2 两个变量互换位置
i, j := 10, 20
i, j = j, i
fmt.Printf("i= %d,j = %d\n", i, j)
2.1.3 匿名函数互换位置
//匿名函数 _函数配合函数 返回值使用
q, w := 10, 20
q, _ = w, q
fmt.Printf("q= %d\n", q)
2.1.4 函数调用
//go函数可以返回多个值
func test() (a, b, c int) {
return 1, 2, 3
}
//调用函数
var c, d, e int
c, d, e = test() //return 1,2,3
2.1.5 匿名函数调用
//匿名函数
_, d, _ = test() //return 1,2,3
fmt.Printf("c =%d , d =%d ,e =%d\n", c, d, e)
2.1.6 常量关键字 const
const a int = 10
fmt.Printf("a =%d", a)
const b = 11.2
2.1.7 枚举iota
2.1.7.1 iota常量自动生成器,每个一行,自动累加1
2.1.7.2 iota给常量赋值使用
//1.iota常量自动生成器,每个一行,自动累加1
//2.iota给常量赋值使用
const (
a = iota //0
b = iota //1
c = iota //2
)
fmt.Printf("a =%d,b =%d ,c =%d", a, b, c)
2.1.7.3 iota遇到const,重置为0
//3.iota遇到const,重置为0
const d = iota //0
fmt.Printf("d =%d\n", d)
2.1.8 字符串
package main
import "fmt"
func main() {
var str1 string
str1 = "abc"
fmt.Println("str1 = ", str1)
//自动推导类型
str2 := "make"
fmt.Println("str2 =", str2)
//内建函数 长度
fmt.Println("len(str2) =", len(str2))
}
2.1.9 复数
var t complex128 //声明
t = 2.1 + 3.14i
fmt.Println("t =", t)
//自动推导类型
t2 := 3.3 + 4.4i
fmt.Printf("t2 type is %T\n", t2)
//通过内建函数,取实部和虚部
fmt.Println("real t2 = ", real(t2))
2.1.10 类型别名
type bigint int64
var a bigint
type (
long int64
char byte
)
var b long = 11
var ch char = 'a'
fmt.Printf("b = %d, ch = %c\n", b, ch)
2.1.11 if类型
//if类型 初始化变量 当a=10时,跳转到括号
if a := 10; a == 10 {
fmt.Println("a =", 10)
}
2.1.11 range类型(迭代)
for i := 0; i < len(str); i++ {
fmt.Printf("str[%d] = %c\n", i, str[i])
}
fmt.Println("------")
//i是下标
for i, data := range str {
fmt.Printf("str[%d]=%c\n", i, data)
}
fmt.Println("------")
for i := range str {
fmt.Printf("str[%d]=%c\n", i, str[i])
}
for i, _ := range str {
fmt.Printf("str[%d]=%c\n", i, str[i])
}
2.1.12 goto类型
//End
fmt.Println("1111")
goto End
fmt.Println("222")
End:
fmt.Println("333")
##2.2
2.2.1函数定义(无返回值)
func Myfunc() {
a := 111
fmt.Println("无参= ", a)
}
func Myfunc1(a int) {
fmt.Println("有参= ", a)
}
func Myfunc2(a int, b int) {
fmt.Printf("a = %d,b=%d\n", a, b)
}
func Myfunc3(a string, b int, c float32) {
fmt.Printf("a = %d,b=%d,c = %d \n,", a, b, c)
}
func main() {
Myfunc()
Myfunc1(222)
Myfunc2(333, 444)
Myfunc3("555", 666, 777.1)
}
2.2.2函数定义(有返回值)
//有返回值
func Myfunc2(a int, b int) (max int, mix int) {
max = a
mix = b
return //有返回值的函数,必须通过return返回
}
func main() {
var a int
_, a = Myfunc2(333, 444)
fmt.Println("a=", a)
}
2.2.3函数类型
func addF(a int, b int) int {
return a + b
}
func minF(a int, b int) int {
return a - b
}
//定义函数类型
//FuncType是一个函数类型
type FuncType func(int, int) int //没有函数名字 没有{}
func main() {
var result int
var TestF = FuncType
TestF = minF
result = TestF(20, 10)
fmt.Println("a=", result)
}
2.2.4函数类型(回调函数,多态)
func add(a int, b int) int {
return a + b
}
//
func addF(a int, b int, dtest FuncType) (result int) {
result = dtest(a, b)
return
}
//定义函数类型
//FuncType是一个函数类型
type FuncType func(int, int) int //没有函数名字 没有{}
func main() {
a := addF(1, 1, add)
fmt.Println("a =", a)
}
2.2.5匿名函数+闭包
func main() {
a := 10
b := 20
//1.定义匿名函数
f1 := func() {
fmt.Println("a = ", a)
fmt.Println("b = ", b)
}
//2.匿名函数类型
type FuncType1 func()
var f2 FuncType1
f2 = f1
f2()
fmt.Println("a =", a)
//3.定义匿名函数
func() {
fmt.Println("a = ", a)
fmt.Println("b = ", b)
}()//()表示调用此函数
//4 有参匿名函数
f4 := func(a,b int) {
fmt.Println("a = ", a)
fmt.Println("b = ", b)
}
f4(4,5)
//5.无名匿名带参数
func(a,b int) {
fmt.Println("a = ", a)
fmt.Println("b = ", b)
}(5,6)//()表示调用此函数
//6.匿名函数有参有返回值
x,y = func(i,j int)(max,min int){
max = i
min = j
return
}(10,20)
}
2.2.5闭包 匿名函数 变量
func test2() func() int {
var x int //没有初始化,值为0
return func() int {
x++
return x * x
}
}
func main() {
f := test2()
//闭包-不关心变量和常量是否已经超出作用于
//只要闭包还在使用它,这些变量就还存在
fmt.Println(f()) //1
fmt.Println(f()) //4
fmt.Println(f()) //9
}
2.2.6 defer的使用
//defer延迟调用 main函数结束前调用
defer fmt.Println("bbb")
fmt.Println("aaaaa")
//有多个defer语句,则是 先进后出 哪怕函数出错 依旧会执行
defer fmt.Println("111")
defer fmt.Println("222")
defer fmt.Println("333")
//匿名函数表示,把变量赋值过去 但是没有调用
defer func(a,b int){
fmt.Printf("a = %d ,b = %c\n",a,b)
}(10,20)
2.2.7 获取命令行参数
func main() {
//要先go build 成 exe
list := os.Args
n := len(list)
fmt.Println("n =", n)
for i := 0; i < n; i++ {
fmt.Printf("list[%d] = %s\n", i, list[i])
}
for i, data := range list {
fmt.Printf("list[%d] = %s\n", i, data)
}
}
2.2.8 变量
1.不同作用域可以有同名变量
2.使用变量的原则,就近原则
2.2.9 导入导出包
//给包起别名
import io "fmt"
io.Println("起别名")
//忽略包
import _ "fmt"
2.2.10 init函数
先执行 init函数 在执行main函数
2.3 复合类型
2.3.1声明变量 指针类型
//变量两含义 1内存 2地址
var num int = 10
fmt.Printf("a = %d\n ", num)
fmt.Printf("a = %v\n ", &num)
//保存变量的地址 需要指针类型
var p *int
p = &num
fmt.Printf("p = %v\n ,&a = %v\n ", p, &num)
2.3.2默认值 nil new函数
var p *int
p = nil
fmt.Println("平= ", p)
//
p := new(int)
*p = 777
2.3.3数组定义赋值
func main() {
var arr [20]int
for i := 0; i < len(arr); i++ {
arr[i] = i + 1
fmt.Printf("arr[%d] = %d\n", i, arr[i])
}
//数组定义 置值,其他值为0
arr1 := [5]int{1, 2, 3}
//指定位置赋值
arr2 := [5]int{2: 1, 3: 4}
fmt.Println(arr2)
}
2.3.4 随机数
import "fmt"
import "time"
import "math/rand"
func main() {
//设置随机数种子
rand.Seed(time.Now().UnixNano()) //当前的系统执行时间
for i := 0; i < 5; i++ {
fmt.Println("rand =", rand.Intn(100))
}
}
2.3.5数组指针
import "fmt"
import "time"
import "math/rand"
//数组指针
//*p 代表指针所指向的内存,就是实参
func modify(p *[5]int) {
//p[0] = 66
(*p)[0] = 666
}
2.3.6切片spilt
func main() {
a := []int{1, 2, 3, 54, 5, 7, 89, 6}
//[low:high:max]
//下标起点 下标终点 (左闭右开) 容量(max-low)
s := a[0:3:5]
fmt.Println("s = ", s) //[1 2 3]
fmt.Println("s len =", len(s)) //长度 3
fmt.Println("s cap =", cap(s)) //容量 5
//创建切片
b := []int{}
//给切片追加一个成员
b=append(b,11)
//不写默认0 从0开始取3个元素.容量为 5-0
s := a[:3:5]
}
2.3.6切片切切片
//切片切切片
a := []int{1, 2, 3, 4, 5, 7, 8, 9}
s1 := a[1:3] //[2,3]
fmt.Println("s1 =", s1)
s2 := s1[1:5] //[3,4,5,7]
fmt.Println("s1 =", s2)
2.3.7 copy函数
a := []int{1, 2, 3, 4, 5}
b := []int{6, 7, 8, 9, 10, 11}
copy(a, b)
fmt.Println("a =", a) //{6, 7, 8, 9, 10}
fmt.Println("b =", b) //{6, 7, 8, 9, 10,11}
2.3.7 map
2.3.7.1 map的定义
func deleMap(mapV map[int]string) {
delete(mapV, 1)
}
//创建map
var map1 map[int]string
fmt.Println("a =", map1) //{6, 7, 8, 9, 10}
//通过make创建
map2 := make(map[int]string)
map2[1] = "make"
map2[2] = "sss"
//定义初始化
map3 := map[int]string{1: "a", 2: 'b'}
//删除
delete(map3, 1)
fmt.Println(map3)
//定义函数
deleMap(map3)
2.3.7.2 map的循环
//定义初始化
map3 := map[int]string{1: "a", 2: "b"}
//循环
for key, value := range map3 {
fmt.Printf("%d =====>%s\n", key, value)
}
//判断一个Key值是否存在
//第一个返回值为key所对应的value
value, ok := m[1]
if ok == true {
fmt.Printf("m[1] =", value)
} else {
fmt.Printf("key不存在")
}
2.3.8 结构体
type Student struct {
id int
name string
sex byte
age int
addr string
}
func main() {
var s1 Student = Student{1, "make", 'm', 20, "背景"}
fmt.Println(s1)//{1 make 109 20 背景}
//指定声明
s2 := Student{name: "make", addr: "背景"}
fmt.Println(s2)//{0 make 0 0 背景}
//声明指针变量
s3 := &Student{name: "make", addr: "背景"}
fmt.Println(s3)//&{0 make 0 0 背景}
var s4 *Student = &Student{1, "make", 'm', 20, "背景"}
fmt.Printf("s4 type= %T\n", s4)//s4 type= *main.Student
fmt.Println(s4)//&{1 make 109 20 背景}
//先定义在赋值
var stu1 Student
stu1.id = 1
stu1.name = "mike"
stu1.sex = '5'
fmt.Println(stu1) //{1 mike 53 0 }
//new申请
stu2 := new(Student)
stu2.id = 1
stu2.name = "mike"
stu2.sex = '5'
fmt.Println(stu2) //&{1 mike 53 0 }
}
2.3.9 可见性
如果想使用别的包的函数,结构体类型,结构体成员,函数名,类型名,结构体成员变量名
首字母必须大写,可见
如果首字母小写,只能能在同一个包里使用
2.4 面向对象编程
2.4.1匿名组合
type Person struct {
id int
name string
age int
}
type Student struct {
Person //只有类型 没有名字,匿名字段 继承了person的成员
garde string
class string
}
2.4.1.2 定义类,赋值,修改
//定义类
var per1 Student = Student{Person{1, "生活", 18}, "初中", "初一"}
fmt.Println("per1", per1)
//自动推导类型
per2 := Student{Person{1, "生活", 18}, "初中", "初一"}
fmt.Printf("per2 %v\n", per2)
//单独复制
per3 := Student{class: "初一"}
fmt.Printf("per3 %v\n", per3)
per4 := Student{Person: Person{id: 5}, class: "初一"}
per4.name = "sss"
per4.Person = Person{5, "aaa", 22}
fmt.Printf("per4 %v\n", per4)
2.4.1.3 匿名字段追加
//非结构匿名字段
type addColum string
func main() {
per2 := Student{Person{1, "生活", 18}, "初中", "初一", "追加字段"}
fmt.Printf("per2 %v\n", per2)//per2 {{1 生活 18} 初中 初一 追加字段}
}
2.4.1.4 地址匿名字段追加
//非结构匿名字段
type addColum string
type Person struct {
id int
name string
age int
}
type Student struct {
*Person //只有类型 没有名字,匿名字段 继承了person的成员
garde string
class string
addColum
}
func main() {
per2 := Student{&Person{1, "生活", 18}, "初中", "初一", "追加字段"}
fmt.Printf("per2 %v\n", per2)
fmt.Println(per2.id, per2.name, per2.age, per2.garde, per2.class)
var per3 Student
per3.Person = new(Person)
per3.addColum = "append"
per3.id = 5
per3.name = "sss"
fmt.Println(per3.id, per3.name, per3.age, per3.garde, per3.class)
}
2.4.2方法
2.4.2.1 定义
//面向对象,方法:给某个类型绑定一个函数
type long int
//tmp叫接受者,接受者传递的一个参数
func (tmp long) Add02(other long) long {
fmt.Println("tmp =", tmp)//1
return tmp + other
}
func main() {
//定义一个变量
var test long = 1
//调用方法格式 :变量名.函数
r := test.Add02(3)
fmt.Println("r =", r)//4
}
2.4.2.2 赋值,输出
//输出函数
func (per Person) pringInfo() {
fmt.Println("per =", per)
}
//赋值函数
func (per Person) setInfo(a int, b string, c int) {
per.id = a
per.name = b
per.age = c
fmt.Println("per =", per)
}
func main() {
per1 := Person{1, "小三", 20}
per1.pringInfo()
per1.setInfo(2, "小三的小三", 21)
}
2.4.2.3 值传递与引用传递
type Person struct {
id int
name string
age int
}
//赋值函数
func (per Person) setInfo(a int, b string, c int) {
per.id = a
per.name = b
per.age = c
fmt.Printf("per = %v\n", per)//per = {3 修改 22}
}
//引用传递
func (per *Person) setInfoPoint(a int, b string, c int) {
per.id = a
per.name = b
per.age = c
fmt.Printf("per = %v\n", per)//per = &{4 修改 32}
}
func main() {
per1 := Person{1, "小三", 20}
per1.setInfo(3, "修改", 22) //引用传递
fmt.Println(per1)//{1 小三 20}
per2 := Person{2, "小三的小三", 21}
per2.setInfoPoint(4, "修改", 32) //值传递
fmt.Println(per2) //{4 修改 32}
}
2.4.2.4 继承传递
type Person struct {
id int
name string
age int
}
type Student struct {
Person
garde string
}
//输出函数
func (per Person) pringInfo() {
fmt.Println("per =", per)
}
func main() {
//继承
stu := Student{Person{5, "小三5", 25}, "s"}
stu.pringInfo()
fmt.Println(stu)
}
2.4.2.5 方法值
stu := Student{Person{5, "小三5", 25}, "s"}
stu.pringInfo()
//方法值 保存方式入口地址
pFunc := stu.pringInfo //这个就是方法值,调用函数时,无需再传递接受者
pFunc() //等价于 stu.pringInfo()
2.4.2.5 方法表达式
//方法表达式
f := (*PePerson).setInfoPoint
f(&stu) //等价于 stu.setInfoPoint()
f1 := (PePerson).setInfo
f1(stu) //等价于 stu.setInfo()
fmt.Println(stu)
2.4.3接口
2.4.3.1 定义
//定义接口
type inter interface {
say()
}
//studnt实现了say方法
func (tmp *Teacher) say() {
fmt.Printf("Studnt %s\n", tmp.zz)
}
func main() {
var i inter
//只要实现 该接口,就可以给这个接口赋值
s := &Teacher{"是啥"}
i = s
i.say()//Studnt 是啥
}
2.4.3.2 继承实现
type inter interface {
say()
}
type inter1 interface {
inter
say1()
}
//studnt实现了say方法
func (tmp *Teacher) say() {
fmt.Printf("Studnt %s\n", tmp.zz)
}
//studnt实现了say1方法
func (tmp *Teacher) say1() {
fmt.Printf("Studnt %s\n", tmp.zz)
}
func main() {
var i inter1
//只要实现 该接口,就可以给这个接口赋值
s := &Teacher{"是啥"}
i = s
i.say()
i.say1()
}
2.4.3.3 接口转换
var i1 inter1 //超集
i1 = &Teacher{"是啥"}
var i inter //子集
i = i1 //可以 超集可以转换为子集
i.say()
2.4.3.4 空接口
i := make([]interface{}, 3)
i[0] = 1
i[1] = "ss"
for index, data := range i {
if value, ok := data.(int); ok == true {
fmt.Printf("index [%v] ,x[%d]\n", index, value)
}
}
2.5 异常处理,字符串
2.5.1错误接口(error)
err1 := fmt.Errorf("%s", "no error")
fmt.Println(err1)
err2 := errors.New("错误")
fmt.Println(err2)
2.5.1.1错误接口的应用
func MyDiv(a, b int) (result int, err error) {
err = nil
if b == 0 {
err = errors.New("B不能为0")
} else {
result = a / b
}
return
}
func main() {
val, err := MyDiv(1, 0)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(val)
}
}
2.5.2函数程序中断(panic)
func test() {
//导致程序中断
panic("this is a panic")
}
2.5.3函数程序(recover)
func test1() {
defer func() {
//err是该函数默认返回值
if err := recover(); err != nil {
fmt.Println(err)
}
}() //()调用此函数
}
2.5.4字符串函数的使用
fmt.Println(strings.Contains("abcdefg", "abc")) //true
arr := []string{"abc", "hello", "arr"}
fmt.Println(strings.Join(arr, "@")) //abc@hello@arr
fmt.Println(strings.Index("abcdefg", "b")) //1
arrStr := "abc@hello@arr"
fmt.Println(strings.Split(arrStr, "@")) //[abc hello arr]
2.5.5 strconv包
arr1 := make([]byte, 0, 1024)
arr1 = strconv.AppendBool(arr1, true)
//整数转字符串
arr2 := strconv.Itoa(6666)
fmt.Println(arr2)
//其他类型转换为字符串
var str string
str = strconv.FormatBool(false)
fmt.Println(str)
2.6 json
2.6.1 结构体转json
import "fmt"
import "encoding/json"
//首字母必须大写
type Student struct {
Id int `json:"-"` //此字段不会输出
Name string `json:"name"` //返回时返回指定字段
Sub []string
IsOk bool `json:",string"` //返回字符串
Price float64
}
func main() {
stu := Student{1, "小明", []string{"go", "java", "php"}, true, 50.00}
fmt.Println(stu)
//json转义
buf, err := json.Marshal(stu)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(buf) //[123 34 73 100 34 58 49 44 34 78 97 109 101 34 58 34 229 176 143 230 152 142 34 44 34 83 117 98 34 58 91 34 103 111 34 44 34 106 97 118 97 34 44 34 112 104 112 34 93 44 34 73 115 79 107 34 58 116 114 117 101 44 34 80 114 105 99 101 34 58 53 48 125]
fmt.Println(string(buf))
}
2.6.2 map转json
map1 := make(map[string]interface{}, 4)
map1["id"] = 5
map1["name"] = "实时"
buf, err := json.MarshalIndent(map1, "", " ")
fmt.Println(string(buf))
fmt.Println(err)
2.6.3 json转实体
func main() {
jsonBuf := `
{
"id": 5,
"name": "实时"
}`
var stu1 Student
json.Unmarshal([]byte(jsonBuf), &stu1)
fmt.Println(stu1)//{0 实时 [] false 0}
}
2.6.4 json转map
func main() {
jsonBuf := `
{
"id": 5,
"name": "实时"
}`
map2 := make(map[string]interface{}, 4)
json.Unmarshal([]byte(jsonBuf), &map2)
fmt.Println(map2)
//断言 判断类型
var str string
for key, value := range map2 {
switch data := value.(type) {
case string:
str = data
fmt.Printf("map[%s]的值类型为string", key)
case []interface{}:
fmt.Printf("map[%s]interface{}", key)
}
}
}
2.7 goroutine并发并行
2.7.1 demo
import "fmt"
import "time"
func newWork() {
for {
fmt.Println("this is newWork")
time.Sleep(1000)
}
}
func main() {
//设置并行处理器
num := runtime.GOMAXPROCS(1)
fmt.Println(num)
//goroutine
go newWork() //新建一个协程任务
for {
fmt.Println("this is mainWork")
time.Sleep(1000)
}
}
2.7.2主协程退出,子协程也退出
func main() {
//主协程退出了,其它子协程也要跟着退出
go func() {
for {
fmt.Println("this is goroutine")
}
}()
i := 0
for {
i++
fmt.Println("this is mainFor")
time.Sleep(1000)
if i > 2 {
break
}
}
}
2.7.3 Goschedr让出调度资源 Goexit 终止
import "runtime"
func main() {
//设置并行处理器
num := runtime.GOMAXPROCS(1)
fmt.Println(num)
//Goschedr
go func() {
for j := 0; j < 2; j++ {
fmt.Println("this is goroutine")
runtime.Goexit() //终止所有协程
}
}()
i := 0
for {
i++
fmt.Println("this is mainFor")
runtime.Gosched() //让出时间片,先让其他协议执行
if i > 2 {
break
}
}
}
2.7.4
2.7.4.1 Demo channel管道
//创建一个无缓存的channel
var ch = make(chan int)
func printWork(val string) {
fmt.Println(val)
fmt.Println(val)
fmt.Println(val)
fmt.Println(val)
fmt.Println(val)
}
func per(sendv string) {
printWork(sendv)
ch <- 666 //给管道协数据,发送
}
func per1(sendv string) {
<-ch //从管道取数据,接收,如果管道没有数据阻塞
printWork(sendv)
}
func main() {
go per("per1")
go per("per2")
for {
}
// per2
// per2
// per2
// per2
// per1
// per1
// per1
}
2.7.4.2 channel 特点
func main() {
var ch3 chan<- float64 //ch3是单向channel 只用于读写float64数据
ch := make(chan int)
//双向隐转单向
var writhCh chan<- int = ch //只能写,不能读
var readCh <-chan int = ch //只能读,不能写
writh <-666 //写
<-readch//读
//单向无法转换为双向
var ch2 chan int = writhCh
}
2.7.4.3 channel 应用
//生产者 只能写,不能读
func product(out chan<- int) {
for i := 0; i < 10; i++ {
out <- i * i
}
close(out)
}
//消费者 只能读,不能写
func consumer(in <-chan int) {
for num := range in {
fmt.Println("consumer=", num)
}
}
func main() {
//创建一个双向通道
ch := make(chan int)
//生产者
go product(ch)
//消费者
consumer(ch)
}
2.7.4.4 定时器
import "time"
func main() {
//只执行一次
timer := time.NewTimer(2 * time.Second)
//重复执行
timer1 :=time.NewTicker(2 * time.Second)
fmt.Println(time.Now())
t := <-timer.C
fmt.Println(t)
timer.Reset(1 * time.Second) //重新设置
timer.Stop() //定时器停止
//2020-06-13 14:06:05.8875131 +0800 CST m=+0.008002001
//2020-06-13 14:06:07.8881753 +0800 CST m=+2.008664201
}
2.7.4.5 select用法
func main() {
ch := make(chan int)
quit := make(chan bool)
//新开一个协程
//读数据
go func() {
for {
select {
case num := <-ch:
fmt.Println("num = ", num)
case <-time.After(3 * time.Second):
fmt.Println("超时")
quit <- true
}
}
}() //自调用
//写数据
for i := 0; i < 5; i++ {
ch <- i
time.Sleep(time.Second)
}
<-quit
fmt.Println("程序结束")
}
2.7.5
2.7.5.1 协议通信过程
应用层 hello
传输层(udp tcp) 源port 目的端口 hello
网络层(ip) 源ip 目的ip 源port 目的端口 hello
链路层(mac) 源mac 目的mac 源ip 目的ip 源port 目的端口 hello
2.7.5.2 tcp传输(服务端)
//传输端
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("err = ", err)
return
}
defer listener.Close()
//阻塞等待用户连接
for {
conn, _ := listener.Accept()
//接受请求
buf := make([]byte, 1024)
n, _ := conn.Read(buf)
//buf[:n] n有多少打印多少 长度是1024所以不可以打印全部
fmt.Println("puf :", string(buf[:n]))
conn.Close()
}
}
2.7.5.3 tcp传输(客户端)
// tcp客户端
package main
import (
"net"
)
func main() {
conn, _ := net.Dial("tcp", "127.0.0.1:8000")
defer conn.Close()
//发送数据
conn.Write([]byte("are you ok?"))
}
2.7.6锁
1.读时共享,写时独享 写锁优先级比读锁高
2.7.6.1 互斥锁
package main
import (
"fmt"
"sync"
"time"
)
var mutex sync.Mutex
var pipeline = make(chan int)
func printWord(word string) {
mutex.Lock()
for _, value := range word {
fmt.Printf("%c",value)
time.Sleep(time.Microsecond*1000)
}
mutex.Unlock()
}
func main() {
go person1()
go person2()
for {
;
}
}
func person1() {
printWord("1111111111111111111")
pipeline<-666
}
func person2() {
<-pipeline
printWord("222222222222222222")
}
2.7.6.2 互斥锁(管道)
package main
import (
"fmt"
"time"
)
var pipeline = make(chan int)
func printWord(word string) {
for _, value := range word {
fmt.Printf("%c",value)
time.Sleep(time.Microsecond*1000)
}
}
func main() {
go person1()
go person2()
for {
;
}
}
func person1() {
printWord("1111111111111111111")
pipeline<-666
}
func person2() {
<-pipeline
printWord("222222222222222222")
}
2.7.6.3 读写锁
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var rwMutes sync.RWMutex //锁只有一把 两个属性
var value int //定义全局变量
func main() {
//播种随机数种子
rand.Seed(time.Now().UnixNano())
for i := 0; i < 5; i++ {
go readWord(i + 1)
}
for i := 0; i < 5; i++ {
go writeWord(i + 1)
}
for {
;
}
}
//写
func writeWord(idw int) {
for {
wnum := rand.Intn(1000)
rwMutes.Lock() //以写模式加锁
value = wnum
fmt.Printf("读 %d==> %d\n", idw, wnum)
time.Sleep(time.Microsecond * 300)
rwMutes.Unlock() //
}
}
//读
func readWord(idx int) {
for {
rwMutes.RLock()
rnum := value
fmt.Printf("写 %d==>%d\n", idx, rnum)
rwMutes.RUnlock()
time.Sleep(time.Millisecond * 300)
}
}
2.7.6.4 读写锁管道
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var rwMutes sync.RWMutex //锁只有一把 两个属性
var value int //定义全局变量
//写
func writeWord(in chan<- int,idw int) {
for {
wnum := rand.Intn(1000)
in<-wnum
fmt.Printf("读 %d==> %d\n", idw, wnum)
time.Sleep(time.Microsecond * 300)
}
}
//读
func readWord(re <-chan int,idx int) {
for {
rnum := <-re
fmt.Printf("写 %d==>%d\n", idx, rnum)
time.Sleep(time.Millisecond * 300)
}
}
func main() {
//播种随机数种子
rand.Seed(time.Now().UnixNano())
ch1 :=make(chan int)
for i := 0; i < 5; i++ {
go readWord(i + 1,ch1)
}
for i := 0; i < 5; i++ {
go writeWord(i + 1,ch1)
}
for {
;
}
}
2.7.6.5条件变量锁
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var cond sync.Cond //创建全局条件变量
func consumer(in <-chan int, idx int) {
for{
cond.L.Lock()//条件变量对应互斥锁枷锁
for len(in) ==0 { //产品区空 等待生产
cond.Wait() //挂起当前携程,等待全局变量满足
}
num:=<-in
fmt.Printf("%d 消费者消费数据 %d,公共区剩余%d个数据\n",idx,num,len(in))
cond.L.Unlock() //生产结束,解锁互斥锁
cond.Signal() //唤醒阻塞的 消费者
time.Sleep(time.Second)//生产完休息一会,
}
}
func producer(out chan<- int, idx int) {
for{
cond.L.Lock() //条件变量对应互斥锁枷锁
//产品区满 等待消费者消费
for len(out)==3{
cond.Wait() //挂起当前携程,等待全局变量满足
}
num := rand.Intn(1000)
out<-num
fmt.Printf("%d 生产者生产数据 %d,公共区剩余%d个数据\n",idx,num,len(out))
cond.L.Unlock() //生产结束,解锁互斥锁
cond.Signal() //唤醒阻塞的 消费者
time.Sleep(time.Second)//生产完休息一会,给其他协程执行机会
}
}
func main() {
rand.Seed(time.Now().UnixNano())//设置随机数种子
quit := make(chan bool) //创建用于结束通信的channel
product := make(chan int, 3) //产品区(公共区)使用channel模拟
cond.L = new(sync.Mutex)//创建互斥锁和条件变量
for i :=0;i<1 ;i++ {
go producer(product,i+1) //5个生产者
}
for i :=0;i<1 ;i++ {
go consumer(product,i+1) //三个消费者
}
<-quit //主线程阻塞 不结束
}
2.7.7 file
2.7.7.1 打开文件
创建文件的步骤:
(1)导入“os”包,创建文件,读写文件的函数都在改包
(2)指定创建的文件存放路径以及文件名。
(3)执行Create( )函数,进行文件创建
(4)关闭文件
//打开文件
package main
import (
"fmt"
"os"
)
func CreataFile(path string){
f, err := os.Create(path)
if err != nil{
fmt.Println("err=",err)
return
}
defer f.Close() //退出关流
}
func main() {
var filePath = "a.txt"
CreataFile(filePath)
}
3.连接mysql
3.1 配置环境变量
3.1.1 设置环境变量 GOPATH
GOPATH
D:\goCode
//项目的安装路径
3.1.2 安装驱动
go get github.com/go-sql-driver/mysql
cmd中打开 这行命令会从github同步代码,同步到GOPATH环境变量下
3.1.3 连接数据库
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
func connectionSql(){
//cannot find package "github.com/go-sql-driver/mysql" in any of:
//idea 配置 file settinf go 配置goPath
var err error
db,err = sql.Open("mysql","root:root@tcp(127.0.0.1:3306)/sxjl?charset=utf8");
//defer db.Close()
if err != nil{
fmt.Printf("connect mysql fail ! [%s]",err)
}
}
3.1.4 查询
/**
查询sql
*/
func querySql(sql string){
rows, err := db.Query(sql)
if err != nil{
fmt.Printf(" mysql fail resion! [%s]",err)
}
//https://blog.csdn.net/kenkao/article/details/47857795?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.nonecase
//字典类型
//构造scanArgs、values两个数组,scanArgs的每个值指向values相应值的地址
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
for rows.Next() {
//将行数据保存到record字典
err = rows.Scan(scanArgs...)
record := make(map[string]string)
for i, col := range values {
if col != nil {
record[columns[i]] = string(col.([]byte))
}
}
fmt.Println(record)
}
}
4.安装Beego
4.1
https://www.cnblogs.com/personblog/p/13084723.html
通用
1.fmt.Sprintf (格式化输出)
%v 按值的本来值输出
%+v 在 %v 的基础上,对结构体字段名和值进行展开
%#v 输出 Go 语言语法格式的值
%T 输出 Go 语言语法格式的类型和值
%% 输出 %% 本体
%b 整型以二进制方式显示
%o 整型以八进制方式显示
%d 整型以十进制方式显示
%x 整型以 十六进制显示
%X 整型以十六进制、字母大写方式显示
%U Unicode 字符
%f 浮点数
%p 指针,十六进制方式显示
2.make 和 new的区别
make 被用来分配引用类型的内存: (make 只能用于 slice,map,channel 三种类型,)
new 被用来分配除了引用类型的所有其他类型的内存: int, string, array等
3.interface{} 类型
interface{} 类型,空接口
//由于没有 implements 关键字,所以所有类型都至少实现了 0 个方法,所以 所有类型都实现了空接口
func PrintAll(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}<br>
}
func main() {
names := []string{"stanley", "david", "oscar"}
//**********必须将[]string 转化为 []interface{}
vals := make([]interface{}, len(names))
for i, v := range names {
vals[i] = v
}
PrintAll(vals)
}
4.参数后面的三个点
Go语言函数中有三个点...表示为可变参数,可以接受任意个数的参数。
ommendFromMachineLearnPai2-6.nonecase
//字典类型
//构造scanArgs、values两个数组,scanArgs的每个值指向values相应值的地址
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
for rows.Next() {
//将行数据保存到record字典
err = rows.Scan(scanArgs...)
record := make(map[string]string)
for i, col := range values {
if col != nil {
record[columns[i]] = string(col.([]byte))
}
}
fmt.Println(record)
}
}
4.安装Beego
4.1
https://www.cnblogs.com/personblog/p/13084723.html
通用
1.fmt.Sprintf (格式化输出)
%v 按值的本来值输出
%+v 在 %v 的基础上,对结构体字段名和值进行展开
%#v 输出 Go 语言语法格式的值
%T 输出 Go 语言语法格式的类型和值
%% 输出 %% 本体
%b 整型以二进制方式显示
%o 整型以八进制方式显示
%d 整型以十进制方式显示
%x 整型以 十六进制显示
%X 整型以十六进制、字母大写方式显示
%U Unicode 字符
%f 浮点数
%p 指针,十六进制方式显示
2.make 和 new的区别
make 被用来分配引用类型的内存: (make 只能用于 slice,map,channel 三种类型,)
new 被用来分配除了引用类型的所有其他类型的内存: int, string, array等
3.interface{} 类型
interface{} 类型,空接口
//由于没有 implements 关键字,所以所有类型都至少实现了 0 个方法,所以 所有类型都实现了空接口
func PrintAll(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}<br>
}
func main() {
names := []string{"stanley", "david", "oscar"}
//**********必须将[]string 转化为 []interface{}
vals := make([]interface{}, len(names))
for i, v := range names {
vals[i] = v
}
PrintAll(vals)
}
4.参数后面的三个点
Go语言函数中有三个点...表示为可变参数,可以接受任意个数的参数。
达梦支持
有任何问题请到技术社区反馈。
24小时免费服务热线:400 991 6599
达梦技术社区:https://eco.dameng.com