一小时捋完GO语法

一小时捋完GO语法

go语言也就是golang,是谷歌发明的一种编程语言,主要特点在于能够快速开发出适应高并发的代码,主要应用在一些云原生环境,比如k8s,gitlab-runner。

本文适用于有点编程语言基础的。可以快速入个门,然后就可以愉快得阅读k8s源代码了。

开发环境

可以参考 centos下VSCode进行GO开发

基础

粗略的扫一遍基本数据结构、运算符、条件、循环、函数、类。有些GO语言特有的先不管,后面慢慢理解。能达到基本的阅读代码水平即可。

  • 关键字:
    • packageimportfuncreturnvarconst
  • 数据类型:
    • boolintstring
  • 运算符:
    • +-*/%++--
  • 关系运算符:
    • ==!=><>=<=
  • 逻辑运算符:
    • &&||!
  • 位运算
    • a = 0011 1100``````b = 0000 1101
    • a&b = 0000 1100
    • a|b = 0011 1101
    • a^b = 0011 0001异或,相异时为1
    • a << 2 = 1111 0000左移
    • a >> 2 = 0000 1111右移
  • 赋值运算,后面几个是位运算的赋值
    • =+=-=*=/=%=&=|=^=<<=>>=
  • 条件语句:
    • if elseswitchselect
  • 循环:
    • for + break + continue + goto
  • 函数格式:
    • func function_name( [parameter_list] ) ( [return_types_list] ) {}
    • 注意可以多返回值
    • 值传递、引用传递
  • 结构体(相当于类)
    • type struct_name struct {}
    • 结构体并不会把函数包含在他的定义中,只需要定义函数时,指定他的结构体就可以。
    • func (struct_var struct_name) function_name( [parameter_list] ) ( [return_types_list] ) {}
  • 接口
    • type interface_name interface {}
    • 如果一个结构体实现了interface中全部的方法,我们认为他实现了这个interface。
    • interface_name val1 = new(struct_name);val1.method1();
  • 变量作用域
    • 全局变量局部变量重名时,优先取局部变量
  • 数组定义
    • var array_name = [size] type_name { var1,var2,var3 }
    • var array_name = [...] type_name { var1,var2,var3 } 自动判断大小
  • 切片
    • 类似数组,但是长度可以自由变化
    • slice_name := array_name[x:y] arr从下标xy-1下的元素创建为一个新的切片
    • make([]T, length, capacity) 创建一个T类型的切片,初始长度length,最大容量capacity
    • appendcopy
  • 集合
    • var map_name map[key_type_name]value_type_name
    • make(map[key_type_name]value_type_name)
  • 范围
    • range用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。
    • for k,v := range kvs {} range返回key value,或者index value
  • 指针
    • var var_name2 type_name = var2
    • var var_name1 *type_name = &var_name2
  • 递归
  • 错误处理,error是一个接口,可以自己定义错误。
    • type error interface{ Error() string }
func ErrorTest()(int,error){
    
    
  return 0,errors.New("error test")
}
  • 并发
    • go func_name(param_list) 即开启了一个 goroutine。
    • 同一个程序中的所有 goroutine 共享同一个地址空间。

特点

变量定义

go的变量定义相当的灵活,可以多个变量一起定义,也可以由编译器自己去分析变量的数据类型。

//注意变量定义有点另类,比如:
var bbsname string
bbsname = "csdn"
//也可以不加类型,系统自己推断
var username = "laowu"
//多变量定义
var key1, key2, key3 = "value1", "value2", "value3"
// := 的赋值,代表变量第一次出现
age, name, chinese := 20, "laowu", true

而go语言的函数也比较有特点,可以定义多个返回值,带来了极大的方便,这里不多说。

异常处理

涉及三个关键字:panicdeferrecover

  • panic类似异常抛出,不遇到recover就进程出错了。
  • recover如上所示,解决panic问题
  • 函数返回前会按照先进后出的顺序调用栈内defer释放资源。

go语言不像java,有try...catch......来处理异常。但是也有一套机制panic...defer...recover...,可以捕捉系统中出现的错误。

但是两者在流程上有不同:

  • try...catch...在try的过程中遇到问题,跳出try代码块,转到catch继续执行。
  • panic...recover...遇到panic后,回溯整个goroutine的调用栈,挨个执行defer,直到遇到defer中的recover或退出。

下例中,app运行过程中,进行了异常处理。

package main
import "fmt"

func main() {
    
    
  for i := 0; i < 10; i++ {
    
    
    calc(i)
  }
}

func calc(n int) {
    
    
  defer func() {
    
     recover() }()
  if n == 5 {
    
    
    panic("panic")
  }
  fmt.Println(" n = ", n)
}

select

尽管select和switch看上去挺像,其实他们的运行机制完全不同。

  • select是针对通信的一个关键词。
  • 每个case代表了一个channel的操作,select能对接多个channel,进行无阻塞的收发操作。
  • 如果同时满足多个case,那么随即执行一个
  • 如果都不满足,则执行default,若没定义default,则一直阻塞,等待。
package main

import (
  "fmt"
  "time"
)

func main() {
    
    
  ch1 := make(chan int)
  ch2 := make(chan int)
  ch3 := make(chan int)

  go func() {
    
     time.Sleep(2 * time.Second); close(ch1) }() //改变时间可以改变事件的发生顺序
  go func() {
    
     time.Sleep(3 * time.Second); close(ch2) }()
  go func() {
    
     time.Sleep(4 * time.Second); close(ch3) }()
  time.Sleep(4 * time.Second) //通过自己休息的时间,可以控制上面三个事件的发生状态。
  for i := 0; i < 1000; i++ {
    
    
  select {
    
    
    case <-ch1:
      fmt.Printf("close ch1")
    case <-ch2:
      fmt.Printf("close ch2")
    case <-ch3:
      fmt.Printf("close ch3")
    }
  }
}

完毕。

猜你喜欢

转载自blog.csdn.net/weixin_36572983/article/details/108109141