Go语言视频零基础入门到精通项目实战web-总结

文章目录

  • day3
    • 1.类型转换
      • 1.1 简单的类型转换
      • 1.2 strconv
      • 1.3 strings
      • 1.4 println 与printf 的区别
    • 2.指针
    • 3.函数参数传递
    • 4.defer
    • 5.匿名函数
    • 6.rune函数
    • 7.课后题 九九表,完数,回文,记录字符数量,两数相加
      • 99
      • 回文
      • 完数
      • 记录字符数量
      • 两数相加
  • day4
    • 1.Go语言中异常处理painc()和recover()的用法
    • 2. 内置函数 new make 递归函数
    • 3. makeSuffix
    • 4. 线程与协程
    • 5.数组
    • 6.go cap和len的区别
    • 7.字符串添加
    • 8.排序
    • 9.map函数
  • day5
    • 1. 排序、链表、二叉树、接口
    • 2.自定义类型的方法
  • day6
    • 接口与反射
  • day7
    • 负载均衡算法
      • 随机
      • 轮播
    • 命令行参数
      • os.Args
    • json
      • struct
      • map
  • day8
    • 文件操作
    • goroute原理
      • 并发、并行
      • 进程、线程、协程
      • 多协程数据交互

编程之久除了算法和数据结构,什么也不属于我们。
编程就是算法和数据结构,算法和数据结构是编程的灵魂。
编程中最没用的东西是源代码,最有用的东西是算法和数据结构。
算法和数据结构是程序的第一秘诀,缺之算法和数据结构是编程的最大原因。
算法和数据结构就是编程的一个重要部分,你若失掉了算法和数据结构,你就把一切都失掉了。

尽管少写那么多代码,但省下来的时间又在哪里呢?
代码是程序员的朋友,虽然没有热情,但是非常忠实。
当你还不能写出自己满意的程序时,你就不要去睡觉。
有些代码不应该被忘记,也没有源代码不应该被记住。
对代码不满足,是任何真正有天才的程序员的根本特征。
有编过程的人的代码,比那些无知的人使用的软件更有价值。
编程是一种美德,是促使一个人不断向上发展的一种原动力。
程序员的一生时间90%是用在编程上,而剩余的10%是活在世界上。
程序员之所以犯错误,不是因为他们不懂,而是因为他们自以为什么都懂。
调试的错误就是编程给你最好的东西,因为在每个错误上面都标志着前进的一步。
假如编程易懂得,那么程序员就不会热情地写出注释,也不会有得到编程的快乐。
代码是最为耐心、最能忍耐和最令人愉快的伙伴,在任何艰难困苦的时刻,它都不会抛弃你

day3

1.类型转换

1.1 简单的类型转换

// 浮点数
a := 5.0

// 转换为int类型
b := int(a)

Go允许在底层结构相同的两个类型之间互转。例如:

// IT类型的底层是int类型
type IT int

// a的类型为IT,底层是int
var a IT = 5

// 将a(IT)转换为int,b现在是int类型
b := int(5)

// 将b(int)转换为IT,c现在是IT类型
c := IT(b)

不是所有数据类型都能转换的,例如字母格式的string类型"abcd"转换为int肯定会失败
低精度转换为高精度时是安全的,高精度的值转换为低精度时会丢失精度。例如int32转换为int16,float32转换为int
这种简单的转换方式不能对int(float)和string进行互转,要跨大类型转换,可以使用strconv包提供的函数
strconv包提供了字符串与简单数据类型之间的类型转换功能。可以将简单类型转换为字符串,也可以将字符串转换为其它简单类型。

1.2 strconv

这个包里提供了很多函数,大概分为几类:

字符串转int:Atoi()
int转字符串: Itoa()
ParseTP类函数将string转换为TP类型:ParseBool()、ParseFloat()、ParseInt()、ParseUint()。因为string转其它类型可能会失败,所以这些函数都有第二个返回值表示是否转换成功
FormatTP类函数将其它类型转string:FormatBool()、FormatFloat()、FormatInt()、FormatUint()
AppendTP类函数用于将TP转换成字符串后append到一个slice中:AppendBool()、AppendFloat()、AppendInt()、AppendUint()

  • int转换为字符串:Itoa()
// Itoa(): int -> string
println("a" + strconv.Itoa(32))  // a32
  • string转换为int:Atoi()
// Atoi(): string -> int
i,_ := strconv.Atoi("3")
println(3 + i)   // 6

// Atoi()转换失败
i,err := strconv.Atoi("a")
if err != nil {
    println("converted failed")
}

数据类型转换

1.3 strings

result := strings.HasPrefix(url,"http://")
	if !result{
		// 返回一个格式化的字符串,并不输出
		url = fmt.Sprintf("http://%s",url)
	}
// 以/ 结尾
result := strings.HasSuffix(path,"/")

// 返回将s中前n个不重叠old子串都替换为new的新字符串,如果n<0会替换所有old子串
str := "hello world abc"
result := strings.Replace(str,"world","you",1)

//返回new_str字符重复次数
strings.count(old_str,new_str) 

// 字符串重复
result = strings.Repeat(str,2)
// hello world abchello world abc

//字符小写
result = strings.ToLower(str)
fmt.Println(result)

//字符大写
result = strings.ToUpper(str)
fmt.Println(result)

field_result := strings.Fields(str)
// 数组 [hello world abc]

split_result := strings.Split(str,"o")
fmt.Println(split_result)
// 去除元素 [hell  w rld abc]

a := "hahaha"
b := "hehehe"
c := strings.Join([]string{a,b},",")
fmt.Println(c)
// hahaha,hehehe 字符串连接

1.4 println 与printf 的区别

Println 有自动换行操作 而Printf没有 但是Printf有占位符的处理

package main

import ("fmt")

func main() {

var test1 int = 1

var test2 int = 2


fmt.Println("哈哈哈%d",test1) //哈哈哈%d 1 有空格

fmt.Println("哈哈哈",test1) //哈哈哈 1

fmt.Printf("哈哈哈%d\n",test1) //哈哈哈1

fmt.Printf("哈哈哈%d%d\n",test1,test2) //哈哈哈12

}

2.指针

Go语言视频零基础入门到精通项目实战web-总结_第1张图片

3.函数参数传递

Go语言视频零基础入门到精通项目实战web-总结_第2张图片

4.defer

当一个方法中有多个defer时, defer会将要延迟执行的方法“压栈”,当defer被触发时,将所有“压栈”的方法“出栈”并执行。所以defer的执行顺序是LIFO的。

example15

// defer
func read()  {
	lock.Lock()
	defer lock.Unlock()
	if i==5{
		return
	}
	if i==10{
		return
	}
	//数据库的连接 最后释放
	conn := openDatabase()
	defer conn.Close()
}

5.匿名函数

example16

func test(a,b int) int {
	result := func(a1,b1 int)int {
		return a1+b1
	}(a,b)
	// return result(a,b)
	return result
}

6.rune函数

rune是Go语言中一种特殊的数据类型,它是int32的别名,几乎在所有方面等同于int32,用于区分字符值和整数值

在Golang中string类型的底层是通过byte数组实现的,在unicode编码中,中文字符占两个字节,而在utf-8编码中,中文字符占三个字节而Golang的默认编码正是utf-8.

如果想要获得真实的字符串长度而不是其所占用字节数,有两种方法实现

  • 方法一:
    使用unicode/utf-8包中的RuneCountInString方法

    str := "hello 世界"
    fmt.Println("RuneCountInString:", utf8.RuneCountInString(str))
    
  • 方法二:
    将字符串转换为rune类型的数组再计算长度

    str := "hello 世界"
    fmt.Println("rune:", len([]rune(str)))
    

7.课后题 九九表,完数,回文,记录字符数量,两数相加

99

//九九乘法表
func table() {
	for i := 0; i <= 9; i++ {
		for a := 1; a <= i; a++ {
			fmt.Printf("%d*%d=%d\t", i, a, i*a)
		}
		fmt.Println()
	}
}

回文

//仅字符 中文len(三个字符)
func huiwen(str string) bool {
	for i := 0; i < len(str); i++ {
		if i == len(str)/2 {
			break
		}
		last := len(str) - i - 1
		if str[i] != str[last] {
			return false
		}
	}
	return true
}

// 中英文都可以
func huiwen1(str string) bool {
	t := []rune(str)
	fmt.Printf(string(t), "\n")
	for i, v := range t {
		if i == len(t)/2 {
			break
		}
		last := len(t) - i - 1
		if t[i] != t[last] {
			return false
		}
		fmt.Printf("%v-%v,%d\n", i, v, len(string(v)))
	}
	return true
}

func main() {
	var str string
	fmt.Scanf("%s",&str)
	if huiwen1(str){
		fmt.Println("yes")
	}else {
		fmt.Println("no")
	}

完数

func perfect(n int) bool {
	var sum int
	for i := 1; i < n; i++ {
		if n%i == 0 {
			sum = sum + i
		}
	}
	return sum == n
}

func process(n int) {
	for i := 1; i < n; i++ {
		if perfect(i) == true {
			fmt.Println(i)
		}
	}
}

func main() {
	var n int
	fmt.Scanf("%d",&n)
	process(n)

记录字符数量

//返回多值加()
func num_str(str string) (word, space, number, other int) {
	t := []rune(str)
	for _, v := range t {
		switch {
		case v >= 'a' && v <= 'z':
			fallthrough
		case v >= 'A' && v <= 'Z':
			word++
		case v == ' ':
			space++
		case v >= '0' && v <= '9':
			number++
		default:
			other++
		}
	}
	return
}
func main() {
	reader := bufio.NewReader(os.Stdin)
	result,_,err:=reader.ReadLine()
	if err !=nil{
		fmt.Println("read is error")
		return
	}
	wc,sc,nc,oc:=num_str(string(result))
	fmt.Printf("word %d\n space %d\n number %d\n other %d\n",wc,sc,nc,oc)
	}

两数相加

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func multi(str1, str2 string) (result string) {

	if len(str1) == 0 && len(str2) == 0 {
		result = "0"
		return
	}

	var index1 = len(str1) - 1
	var index2 = len(str2) - 1
	var left int

	for index1 >= 0 && index2 >= 0 {
		c1 := str1[index1] - '0'
		c2 := str2[index2] - '0'

		sum := int(c1) + int(c2) + left
		if sum >= 10 {
			left = 1
		} else {
			left = 0
		}
		c3 := (sum % 10) + '0'
		result = fmt.Sprintf("%c%s", c3, result)
		index1--
		index2--
	}

	for index1 >= 0 {
		c1 := str1[index1] - '0'
		sum := int(c1) + left
		if sum >= 10 {
			left = 1
		} else {
			left = 0
		}
		c3 := (sum % 10) + '0'

		result = fmt.Sprintf("%c%s", c3, result)
		index1--
	}

	for index2 >= 0 {
		c1 := str2[index2] - '0'
		sum := int(c1) + left
		if sum >= 10 {
			left = 1
		} else {
			left = 0
		}
		c3 := (sum % 10) + '0'
		result = fmt.Sprintf("%c%s", c3, result)
		index2--
	}

	if left == 1 {
		result = fmt.Sprintf("1%s", result)
	}
	return
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	result, _, err := reader.ReadLine()
	if err != nil {
		fmt.Println("read from console err:", err)
		return
	}

	strSlice := strings.Split(string(result), "+")
	if len(strSlice) != 2 {
		fmt.Println("please input a+b")
		return
	}

	strNumber1 := strings.TrimSpace(strSlice[0])
	strNumber2 := strings.TrimSpace(strSlice[1])
	fmt.Println(multi(strNumber1, strNumber2))
}

day4

1.Go语言中异常处理painc()和recover()的用法

Go语言提供了recover内置函数,前面提到,一旦panic,逻辑就会走到defer那,那我们就在defer那等着,调用recover函数将会捕获到当前的panic(如果有的话),被捕获到的panic就不会向上传递了,于是,世界恢复了和平。你可以干你想干的事情了。

package main
 
import "fmt"
 
func main(){
    defer func(){ // 必须要先声明defer,否则不能捕获到panic异常
        fmt.Println("c")
        if err:=recover();err!=nil{
            fmt.Println(err) // 这里的err其实就是panic传入的内容,55
        }
        fmt.Println("d")
    }()
    f()
}
 
func f(){
    fmt.Println("a")
    panic(55)
    fmt.Println("b")
    fmt.Println("f")
}

2. 内置函数 new make 递归函数

example2:

new:它返回的永远是类型的指针,指向分配类型的内存地址。

make:也是用于内存分配的,但是和new不同,它只用于chan、map以及切片的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

递归:一个大问题可以拆分成很多个小问题时,可以用递归

3. makeSuffix

func makeSuffix(suffix string) func(string) string {
	f := func(name string) string {

		if strings.HasSuffix(name, suffix) == false {
			return name + suffix
		}
		return name
	}

	return f
func main() {
	f1 := makeSuffix(".bmp")
	fmt.Println(f1("test"))
	fmt.Println(f1("pic"))

4. 线程与协程

xiecheng:
https://blog.csdn.net/TDCQZD/article/details/82684636

func fab(n int) {
	var a []int
	a = make([]int, n)
	fmt.Println(a)

	a[0] = 1
	a[1] = 1

	for i := 2; i < n; i++ {
		a[i] = a[i-1] + a[i-2]
	}

	for _, v := range a {
		fmt.Println(v)
	}
}

5.数组

example6:

func testArray2() {
	var a [2][5]int = [...][5]int{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}}

	for row, v := range a {
		for col, v1 := range v {
			fmt.Printf("(%d,%d)=%d ", row, col, v1)
		}
		fmt.Println()
	}
}
//(0,0)=1 (0,1)=2 (0,2)=3 (0,3)=4 (0,4)=5 
//(1,0)=6 (1,1)=7 (1,2)=8 (1,3)=9 (1,4)=10 

6.go cap和len的区别

首先要搞清楚容量和长度的区别:

容量是指底层数组的大小,长度指可以使用的大小

容量的用处在哪?在与当你用 appen d扩展长度时,如果新的长度小于容量,不会更换底层数组,否则,go 会新申请一个底层数组,拷贝这边的值过去,把原来的数组丢掉。也就是说,容量的用途是:在数据拷贝和内存申请的消耗与内存占用之间提供一个权衡。

而长度,则是为了帮助你限制切片可用成员的数量,提供边界查询的。所以用 make 申请好空间后,需要注意不要越界【越 len 】

func testSlice()  {
	var a[]int = []int{1,2,3,4,5}
	s :=a[1:]
	fmt.Println(a[1])
	fmt.Printf("s=%p, a[1]=%p,len()=%d,cap=%d\n",s,&a[1],len(s),cap(s)) //内存地址不变
	// s=0xc00000e2d8, a[1]=0xc00000e2d8,len()=4,cap=4
	s = append(s, 10)// 越界,内存变化
	s = append(s, 10)
	s = append(s, 10)
	fmt.Println(s)
	fmt.Printf("s=%p, a[1]=%p,len()=%d,cap=%d\n",s,&a[1],len(s),cap(s)) //内存地址变
	// s=0xc00000c2c0, a[1]=0xc00000e2d8,len()=7,cap=8
}

7.字符串添加

func testModifyString()  {
	s:="我hello world"
	s1 := []rune(s) //转为rune类型 不能用byte
	fmt.Println(s1)
	// [104 101 108 108 111 32 119 111 114 108 100]
	s1[1]='0'
	fmt.Println(s1)
	// [104 48 108 108 111 32 119 111 114 108 100]
	fmt.Println(string(s1))
	// 我h0llo world
}

8.排序

sort.Ints(a)
sort.Strings(a)
sort.Float64s(a)

var a=[]int{3,2,6,111,9}
sort.Ints(a)
b:=sort.SearchInts(a[:], 2)//查找默认排序后的 2下标

map排序需遍历,然后sort排序

9.map函数

//a[]=""
func testMap()  {
	var a map[string]string=map[string]string{
		"key":"values",
	}
	//a=make(map[string]string,10)//分配内存空间
	a["abc"]="qwer"
	a["abc"]="qwer"
	a["y"]="qwer"
	fmt.Println("test1",a)
}
func testMap2()  {
	a:=make(map[string]map[string]string,100)
	a["key1"]=make(map[string]string)
	a["key1"]["key2"] ="abc"
	a["key1"]["key3"] ="abc"
	a["key1"]["key4"] ="abc"
	a["key1"]["key5"] ="abc"
	fmt.Println(a)
	// map[key1:map[key2:abc key3:abc key4:abc key5:abc]]
}

func testMap3()  {
	a:=make(map[string]map[string]string,100)

	_,ok :=a["zhangsan"]
	if !ok{
		a["zhangsan"]=make(map[string]string)
	}
	a["zhangsan"]["password"] ="123456"
	a["zhangsan"]["nickname"]="pangpang"
	fmt.Println(a)
	// map[zhangsan:map[nickname:pangpang password:123456]]
}
// a[""][""]=""
func testMap4()  {
	a:=make(map[string]map[string]string,100)
	a["key1"]=make(map[string]string)
	a["key1"]["key2"] ="abc"
	a["key1"]["key3"] ="abc"
	a["key1"]["key4"] ="abc"
	a["key1"]["key5"] ="abc"
	a["key2"]=make(map[string]string)
	a["key2"]["key4"] ="abc"
	a["key2"]["key5"] ="abc"
	for k,v :=range a["key1"]{
		fmt.Println(k,v)
	}
	delete(a,"key1")
	fmt.Println(a)
	fmt.Println(len(a))
	//key2 abc
	//key3 abc
	//key4 abc
	//key5 abc
	//map[key2:map[key4:abc key5:abc]]
	//1
}
// a[]=int
func testMap5()  {
	var a[]map[int]int
	a =make([]map[int]int,5) //分配内存空间
	fmt.Println(a)
	if a[0]==nil{
		a[0]=make(map[int]int)
	}
	a[0][10]= 100
	fmt.Println(a)
	//[map[10:100] map[] map[] map[] map[]]
}

day5

1. 排序、链表、二叉树、接口

2.自定义类型的方法

package main

import "fmt"

type integer int

func (p integer) print() {
	fmt.Println("p is ", p)
}

func (p *integer) set(b integer) {
	*p = b
}

type Student struct {
	Name  string
	Age   int
	Score int
	sex   int
}

func (p *Student) init(name string, age int, score int) {
	p.Name = name
	p.Age = age
	p.Score = score
	fmt.Println(p)
}

func (p Student) get() Student {
	return p
}

func main() {
	var stu Student
	stu.init("stu", 10, 200)

	stu1 := stu.get()
	fmt.Println(stu1)

	var a integer
	a = 100
	a.print()

	a.set(1000)
	a.print()
}
//&{stu 10 200 0}
//{stu 10 200 0}
//p is  100
//p is  1000

day6

接口与反射

package main

import "fmt"

type Carer interface {
	GetName() string
	Run()
	DiDi()
}

type Test interface {
	Hello()
}

type BMW struct {
	Name string
}

func (p *BMW) GetName() string {
	return p.Name
}

func (p *BMW) Run() {
	fmt.Printf("%s is running\n", p.Name)
}

func (p *BMW) DiDi() {
	fmt.Printf("%s is didi\n", p.Name)
}

func (p *BMW) Hello() {
	fmt.Printf("hello, i'm %s \n", p.Name)
}

type BYD struct {
	Name string
}

func (p *BYD) GetName() string {
	return p.Name
}

func (p *BYD) Run() {
	fmt.Printf("%s is running\n", p.Name)
}

func (p *BYD) DiDi() {
	fmt.Printf("%s is didi\n", p.Name)
}

func main() {
	var car Carer
	var test Test

	fmt.Println(car)

	bmw := &BMW{
		Name: "BMW",
	}

	car = bmw
	car.Run()

	test = bmw
	test.Hello()

	byd := &BYD{
		Name: "BYD",
	}

	car = byd
	car.Run()
}

example9:

package main

import (
	"encoding/json"
	"fmt"
	"reflect"
)

type Student struct {
	Name  string `json:"student_name"`
	Age   int
	Score float32
	Sex   string
}

func (s Student) Print() {
	fmt.Println("---start----")
	fmt.Println(s)
	fmt.Println("---end----")
}

func (s Student) Set(name string, age int, score float32, sex string) {

	s.Name = name
	s.Age = age
	s.Score = score
	s.Sex = sex
}

func TestStruct(a interface{}) {
	tye := reflect.TypeOf(a)
	val := reflect.ValueOf(a)
	kd := val.Kind()
	if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct {
		fmt.Println("expect struct")
		return
	}

	num := val.Elem().NumField()
	val.Elem().Field(0).SetString("stu1000")// 改变值
	for i := 0; i < num; i++ {
		// Elem()指针改为变量
		fmt.Printf("%d %v %v\n", i, val.Elem().Field(i),val.Elem().Field(i).Kind())
	}

	fmt.Printf("struct has %d fields\n", num)

	tag := tye.Elem().Field(0).Tag.Get("json")
	fmt.Printf("tag=%s\n", tag)

	numOfMethod := val.Elem().NumMethod()
	fmt.Printf("struct has %d methods\n", numOfMethod)
	var params []reflect.Value
	val.Elem().Method(0).Call(params)
}

func main() {
	var a Student = Student{
		Name:  "stu01",
		Age:   18,
		Score: 92.8,
	}
	fmt.Println(a)
	result, _ := json.Marshal(a)//变为json格式
	fmt.Println("json result:", string(result))

	TestStruct(&a) //传地址
	fmt.Println(a)
}

day7

负载均衡算法

随机

package balance

import (
	"errors"
	"math/rand"
)

func init() {
	RegisterBalancer("random", &RandomBalance{})
}

type RandomBalance struct {
}

func (p *RandomBalance) DoBalance(insts []*Instance, key ...string) (inst *Instance, err error) {

	if len(insts) == 0 {
		err = errors.New("No instance")
		return
	}

	lens := len(insts)
	index := rand.Intn(lens)
	inst = insts[index]

	return
}

轮播

package balance
// 轮播
import (
	"errors"
)

func init() {
	RegisterBalancer("roundrobin", &RoundRobinBalance{})
}

type RoundRobinBalance struct {
	curIndex int  //当前机器索引
}

func (p *RoundRobinBalance) DoBalance(insts []*Instance, key ...string) (inst *Instance, err error) {

	if len(insts) == 0 {
		err = errors.New("No instance")
		return
	}

	lens := len(insts)
	if p.curIndex >= lens {
		p.curIndex = 0
	}

	inst = insts[p.curIndex]
	//假如有三台机器,加了一台越界 4/3 取余数 1
	p.curIndex = (p.curIndex + 1) % lens
	return
}

命令行参数

os.Args

func main() {
	fmt.Printf("len of args:%d\n", len(os.Args))
	for i, v := range os.Args {
		fmt.Printf("args[%d]=%s\n", i, v)
	}
}
go run main.go 655 655
args[0]=C:\Users\ADMINI~1\AppData\Local\Temp\go-build201241730\b001\exe\main.exe
args[1]=655
args[2]=655

json

example9

struct

package main

import (
	"encoding/json"
	"fmt"
)

type User struct {
	UserName string `json:"username"`
	NickName string `json:"nickname"`
	Age      int
	Birthday string
	Sex      string
	Email    string
	Phone    string
}

func testStruct() (ret string, err error) {
	user1 := &User{
		UserName: "user1",
		NickName: "上课看似",
		Age:      18,
		Birthday: "2008/8/8",
		Sex:      "男",
		Email:    "[email protected]",
		Phone:    "110",
	}

	data, err := json.Marshal(user1)
	if err != nil {
		err = fmt.Errorf("json.marshal failed, err:", err)
		return
	}

	ret = string(data)
	return
}
func test() {
	data, err := testStruct()
	if err != nil {
		fmt.Println("test struct failed, ", err)
		return
	}

	var user1 User
	//反序列成结构体
	err = json.Unmarshal([]byte(data), &user1) //字符串转为字符数组   传指针
	if err != nil {
		fmt.Println("Unmarshal failed, ", err)
		return
	}
	fmt.Println(user1)
}

func main() {
	test()
	test2()
}

map

func testMap() (ret string, err error) {
	var m map[string]interface{}
	m = make(map[string]interface{})
	m["username"] = "user1"
	m["age"] = 18
	m["sex"] = "man"

	data, err := json.Marshal(m)
	if err != nil {
		err = fmt.Errorf("json.marshal failed, err:", err)
		return
	}

	ret = string(data)
	return
}

func test2() {
	data, err := testMap()
	if err != nil {
		fmt.Println("test map failed, ", err)
		return
	}

	var m map[string]interface{}
	// map里面插数据 不需要传地址 改变map本身 需要传地址
	err = json.Unmarshal([]byte(data), &m)
	if err != nil {
		fmt.Println("Unmarshal failed, ", err)
		return
	}
	fmt.Println(m)
}

day8

文件操作

func main()  {
	file ,err :=os.Open("D:/abc.txt")
	if err !=nil{
		fmt.Println(err)
		return
	}
	defer file.Close()
	reader := bufio.NewReader(file)

	for{
		data,prefix,err :=reader.ReadLine()
		if err == io.EOF {
			break
		}
		if !prefix {
			fmt.Printf("%s\n", string(data))
		}
	}
}

goroute原理

并发、并行

进程、线程、协程

多协程数据交互

//读少写多 互斥  读多写少 读写锁
//m 为全局变量  需加锁
var(
	m =make(map[int]uint64)
	lock sync.Mutex
)

type task struct {
	n int
}

func calc(t *task) {
	var sum uint64
	sum = 1
	for i := 1; i < t.n; i++ {
		sum = sum * uint64(i)
	}
	lock.Lock()
	m[t.n]=sum
	lock.Unlock()

}

func main() {
	for i := 0; i < 1000; i++ {
		t := &task{n: i}
		go calc(t)
	}
	time.Sleep(3*time.Second)
	lock.lock()
	for k,v :=range m{
		fmt.Printf("%d = %v\n" ,k,v)
	}
	lock.Unlock()
}

你可能感兴趣的:(Golang)