go语言学习 五

第一个就是 还是重启电脑 然后在输入密码的时候不要输入 按住shift和关机那的重启按钮 会进入安全操作界面,里边有一个疑难解答进去,然后在里边找到高级选项 里边有一个启动设置,然后点重启,刚刚让你按的是4或者f4选的是安全模式 ,你现在看里边有没一个模式叫做启动带网络连接的安全模式,然后按他对应的序号 如果说有 并且进去了,那就先这么用 能上网 但是我也不确定什么东西会受到限制 遇到问题了再说

 

如果说里边没有带网络连接的安全模式 那就进入咋们刚刚进去的安全模式 进去之后点开始设置,然后找到设备里边的设备管理器,应该是在设备里边找到设备管理器,然后到时候看看有没有设备前边有感叹号什么一类的一看就是不正常的那种。有的话就处理一下,没有的话 你就用腾讯安全管家杀杀毒,然后看看有没有什么新安装的软件 卸载了 处理一下

 

在任何语言里边都有对输入和输出的实现,go语言中提供了fmt包帮我们格式化输出字符串,其中最常用的是 fmt.Printf和fmt.Println Printf和c语言中printf是类似的,可以指定格式化比如%d %v等格式输出,println是单穿的将参数字符串化然后进行输出,实际上这两个函数在执行的时候,都会对将传入的参数对象查询并调用一个stringer接口 这个stringer接口有个string方法返回一个描述实例自身的字符串,但是实际上只要有参数的类型实现了string方法即可。

 1 package main                                                               

  2

  3 import "fmt"

  4

  5 type student struct {

  6     name string

  7     age int

  8 }

  9

 10 func (s student) String() string{

 11     return fmt.Sprintf("student name is %s age is %d",s.name,s.age)

 12 }

 13

 14 func main(){

 15     s:=student{"jiahaonan",22}

 16     fmt.Println(s)

 17 }

 

比如上边的程序中我们定义了自定义的结构体,然后通过fmt包中提供的借口定义了string函数然后在里边进行了格式化输出,这样下次直接调用Println的时候就会直接进行格式化输出. 因为我们定义了显示的string方法,fmt就不调用默认的string方法

 

 

 

Go语言中有一个goroutine的概念,groutine是由go运行的时候管理的轻量级的线程 go f(x,y,z) 会启动一个新的go程来执行f函数,里边的参数 xyz求值会在当前的go程中执行,而f的执行发生在新的go中

 

package main

 

import (

    "fmt"

    "time"

)

 

func say(s string) {

    for i := 0; i < 5; i++ {

        time.Sleep(100 * time.Millisecond)

        fmt.Println(s)

    }

}

 

func main() {

    go say("world")

    say("hello")

}

 

在这个程序中,主函数中我们另外起了一个go程也就是一个线程来执行say,然后之后当前线程中也执行了say函数

go语言学习 五_第1张图片

所以当执行主函数程序的时候就会出现hello和world交替打印的现象,并且如果修改say函数里的休眠时长交替打印的顺序就会改变 。

有了不同的线程自然就少不了线程之间的通信,channel时go语言里边一个机制,它在两个兵法之行的函数之间进行同步,并通过传递(与该信道元素类型相符的)值来进行通信。本质上channel就是一个管道或者说是一个先进先出的队列,非常简单并且轻量

 

package main

 

import "fmt"

 

func sum(s []int, c chan int) {

    sum := 0

    for _, v := range s {

        sum += v

    }

    c <- sum // 将和送入 c

}

 

func main() {

    s := []int{7, 2, 8, -9, 4, 0}

 

    c := make(chan int)

    go sum(s[:len(s)/2], c)

    go sum(s[len(s)/2:], c)

    x, y := <-c, <-c // 从 c 中接收

 

    fmt.Println(x, y, x+y)

}

 

在这个程序里go出来两个线程然后通过make创建好信道,信道里边主要要指定好类型,只能接受对应类型的数据。然后在执行好函数内部往信道内部传输数据,在函数内部接受对应的数据。我们上边make的信道是一个最基础的正常的信道,信道也是可以有带缓冲区的信道,是将缓冲长度作为第二个参数提供给make来初始化一个带缓冲的信道,只有当信道缓冲区满的时候向其发送数据时才会阻塞,当缓冲区为空的时候接收方才会阻塞,

ch := make(chan int, 2) 这里是设定了一个长度为2的缓冲信道

 

package main

 

import (

    "fmt"

)

 

func fibonacci(n int, c chan int) {

    x, y := 0, 1

    for i := 0; i < n; i++ {

        c <- x

        x, y = y, x+y

    }

    close(c)

}

 

func main() {

    c := make(chan int, 10)

    go fibonacci(cap(c), c)

    for i := range c {

        fmt.Println(i)

    }

}

发送者可以通过close关闭一个信道 来表示没有要发送的数据了,接受这可以通过为接受表达式分配第二个参数来测试信道是否被关闭若没有值可以接受且信道已经被关闭,那么在执行完之后

v, ok := <-ch 之后ok会被设置为false 循环for I:=range c会不断的从信道接受值 知道他被关闭。这里要注意的是,只有发送者可以关闭一个信道,接受者是不可以关闭信道的,向一个已经关闭的信道发送数据会引发程序panic 信号和文件不同通常来说可以不关闭他们,除非只有在必须告诉接受者不再有需要发送的值时才有必要关闭。

select语句可以让一个go程等待多个通信操作select会阻塞到某个分之可以继续执行位置,这时候就会执行该分支,如果多个分支都准备好就会随机选择一个执行。当其他所有分支都没有准备好的时候default分支就会执行。

有了多进程多线程就必然想到了通信,同时也必然有锁的存在同样go语言标准库里边提供了sync.mutex互斥锁。

这里我们同时让一千个线程去操作我们的map往对应map的key值对应的value进行++操作。

如果害怕在拿到锁的中间会有意外导致死锁我们可以使用之前介绍过的defer语句来保证互斥锁一定会被释放。

你可能感兴趣的:(实习)