GO的第二天

今天主要去看了一下官方网站,网站:https://gobyexample.com/

进行了简单的摘要。依旧是不会写博客的一天(有java基础的哦,虽然也不太行)


Constants:常量

Slices:切片  s := make([]string, 3) //长度为3的切片

              fmt.Println("len:", len(s))//返回长度

              s = append(s, "d")//压入新的

              l := s[2:5]//得到一个包含元素 s[2]、s[3] 和 s[4] 的 slice (做包右面不包除非【2:】后面都包括) 

Map:关联数据类型    m := make(map[string]int)//创建新的map

                  n := map[string]int{"foo": 1, "bar": 2}//声明并初始化map

                  m["k1"] = 7//设置键值对 

                  fmt.Println("len:", len(m))//内建函数 len 可以返回一个 map 的键值对数量。

                  delete(m, "k2")//内建函数 delete 可以从一个 map 中移除键值对。

Range 遍历(for)      for _, num := range nums {sum += num}//无索引遍历(无key)

                    for i, num := range nums {if num == 3 {fmt.Println("index:", i)}}//有索引value=3时返回key

                    for i, c := range "go" { fmt.Println(i, c) }//range 在字符串中迭代 unicode 码点(code point)。 第一个返回值是字符的起始字节位置,然后第二个是字符本身。

函数    func plusPlus(a, b, c int) int { return a + b + c}//a,b,c类型相同可以只声明最后一个

        多返回值(同时返回结果和错误信息)      func vals() (int, int) {return 3, 7}//(int,int)表示返回两个int

                                              _, c := vals()//仅返回一部分即7

        变参函数      func sum(nums ...int) {}//接受任意数量的int                 

                      sum(nums...)// func函数名(slice切片...)直接求和

        函数特性

                      闭包  https://gobyexample-cn.github.io/closures

                      递归  https://gobyexample-cn.github.io/recursion

指针    func zeroptr(iptr *int) {*iptr = 0}//*int代表使用指针,*iptr解引用这个指针

        zeroptr(&i)//通过&i取得i的内存地址

        fmt.Println("zeroptr:", i)

        fmt.Println("pointer:", &i)//打印地址

结构体  type 结构体名persnon struct { name string  age  int}//创建结构体

        fmt.Println(person{"Bob", 20})//创建新的结构体元素

        fmt.Println(person{name: "Alice", age: 30})//可以指定字段元素

        fmt.Println(person{name: "Fred"})//省略字段初始化为零

        fmt.Println(&person{name: "Ann", age: 40})//& 前缀生成一个结构体指针。

        fmt.Println(s.name)//s的name,用“.”

        sp.age = 51//结构体可变,重新赋值51

方法  支持位结构体定义方法

      func (r *rect) area() int {return r.width * r.height}//接受*rect,返回int


接口    type geometry interface {area() float64 perim() float64}//接口的实现

        func measure(g geometry) {}//通常使用measure函数来实现,通过它使用所有的接口

错误处理  func f1(arg int) (int, error) {//返回一个int和一个错误

              if arg == 42 {return -1, errors.New("can't work with 42")//构建error

              return arg + 3, nil//返回错误值为 nil 代表没有错误

          }

          type argError struct { arg  int prob string }//可以自定义错误类型

          func (e *argError) Error() string {

              return fmt.Sprintf("%d - %s", e.arg, e.prob)

          }//Sprint格式化输出,输出形式为%d - %s

          for _, i := range []int{7, 42} {//在if的同一行进行错误检查

                    if r, e := f1(i); e != nil {

                        fmt.Println("f1 failed:", e)

                    } else {

                        fmt.Println("f1 worked:", r)

                    }

            }

协程:量级的执行线程      go f("goroutine")//多线程开启,并发开启

                        go func(msg string) { fmt.Println(msg) }("going")//传入going并发异步执行

                        time.Sleep(time.Second)//等待进程完成,更好的方法是使用 WaitGroup

                        go func(){}()//以并发的形式调用函数

通道:连接多个协程的管道        messages := make(chan string)//创建新的通道(通道类型就是要传递值的类型)

                            go func() { messages <- "ping" }()//channel <-值,这样发送值到通道

                            msg := <-messages//接受通道里的值

        通道缓冲:允许在没有对应接收者的情况下,缓存一定数量的值

                  messages := make(chan string, 2)//最多允许缓存两个值的通道

                  messages <- "buffered"  messages <- "channel"//直接发送,无需发送之后马上接收


        通道同步:可以使用通道来同步协程之间的执行状态

                  func worker(done chan bool) {//一个叫done的通道和一个bool

                        fmt.Print("working...")

                        time.Sleep(time.Second)

                        fmt.Println("done")

                        done <- true//done用于通知工作ok

                        如果你把 <- done 这行代码从程序中移除, 程序甚至可能在 worker 开始运行前就结束了。

                  }


        通道方向:可以指定这个通道是否为只读或只写,可以提升程序的安全性

                  func ping(pings chan<- string, msg string) {//定义了只写(发送)权限

                                pings <- msg

                  }

                func pong(pings <-chan string, pongs chan<- string) {//接收两个通道,pings用于只读(接受),pongs用于只写(发送)

                                msg := <-pings

                                pongs <- msg

                }

          通道选择器:可以同时等待多个通道操作

                    select {}//用select关键字来同时等待这两个值,默认处理第一个准备好的接受操作

                    time.Sleep(1 * time.Second)//等待的时间短的先输出,程序运行的时间是等待长的时间而不是和

          超时处理        case <-time.After(1 * time.Second)://等待时间之后向通道传入

                        select {

                                    case res := <-c1:

                                          fmt.Println(res)

                                    case <-time.After(1 * time.Second)://如果操作耗时超过了允许的 1 秒(时间),执行这个

                                          fmt.Println("timeout 1")

                          }

                          如果正常时间<超时时间,则不触发超时时间

          非阻塞通道操作:常规通道是阻塞的。 可以用default,select实现非阻塞发送、接收,甚至是非阻塞的多路 select。

                      msg := "hi"

                      select {

                                  case messages <- msg:

                                          fmt.Println("sent message", msg)//发送msg必须有人收才会被选中,否则不会。

                                  default:

                                          fmt.Println("no message sent")//输出结果为这个

                              }

                        select {

                                    case msg := <-messages://如果messages有值(接收必须有人发才会被选中)

                                            fmt.Println("received message", msg)

                                    case sig := <-signals://如果signals有值

                                            fmt.Println("received signal", sig)

                                    default://否则

                                            fmt.Println("no activity")

                        }

          通道的关闭:这个特性可以让通道的接收方知道工作完成

                    j, more := <-jobs//工作完成或关闭通道more为false

                    if more {}

                    else {

                            fmt.Println("received all jobs")

                            done <- true

                            return

                    }

                    close(jobs)//关闭通道

                    <-done//等待工作结束

          通道遍历:类似for和range

                  queue := make(chan string, 2)

                  queue <- "one"

                  queue <- "two"

                  close(queue)//非空通道也可以关闭,关闭后可以正常接收

                  for elem := range queue { fmt.Println(elem) }//循环输出通道的值

Timer:定时器在一定时间之后要发生的事,它会提供一个用于通知的通道。与sleep的区别在于定时器可以在定时器触发之前取消。需要import time

      timer1 := time.NewTimer(2 * time.Second)//这里的定时器等待2秒

      <-timer1.C//c为定时器通道

      stop2 := timer2.Stop()//停止定时器

Ticker:打点器在固定的时间间隔重复执行知道主动停止,停止后不能接受值

      ticker := time.NewTicker(500 * time.Millisecond)//创建打点器

      case t := <-ticker.C:  fmt.Println("Tick at", t)//触发打点器

      ticker.Stop()//结束打点器

推荐阅读更多精彩内容

  • 简介 go语言的协程是十分轻量级的线程,它的销毁创建都在用户空间,因此一般没有必要对协程进行限制,但是某些场景还是...
    小昔小怪兽阅读 157评论 0 0
  • 官网文档[https://www.yuque.com/tal-tech/go-zero/rm435c] 其实说得很...
    daydaygo阅读 465评论 0 0
  • 数据定义 1.函数返回值问题: 在函数有多个返回值时,只要有⼀个返回值有名 称,那么其他返回值也⼀定要有名称 2....
    余生社会阅读 221评论 0 0
  • 1、对称加密Nacl包的使用 2、AES-GCM加密 3、AES-CTR with HMAC加密
    汪明军_3145阅读 122评论 0 0
  • 作者:结冰 前言 ​ 说在最前面,我是一个外表谦让,内心狂热,外表斯文,内心贪玩的一个普通人。我的职业是程序员...
    kevwan阅读 461评论 0 2