golang的关键字

变量

var声明创建一个具体类型的变量,

  • var name type = expression

Go是一种静态类型的语言,但是它仍然提供了一种在声明变量的同时省略数据类型声明的功能,类型和表达式可以省略一个,但是不能都省略;也就是golang支持类型推断

  • var s string  var b, f, s = true, 2, 3;

短变量声明

Golang中有两种创建变量的方法,如下所示:

  • 使用var关键字

  • 使用短变量声明运算符(:=)

使用短变量声明运算符的语法:

variable_name := 表达式 或 值    必须在声明后立即初始化变量,无需提及变量的类型, 右侧的表达式或值用于评估变量的类

声明仅具有块级作用域的局部变量

因其短小灵活,所以在局部变量的声明以及初始化中用的较多

:= 表示声明  而 = 表示赋值

只有在同一个词法语块中已经存在变量的情况下,短变量的行为才和赋值操作一样

go lang 中指针和clang 指针差不多

  • 指针的声明和初始化可以在一行中完成。

    var s *int = &a

*运算符 也称为解引用运算符,用于声明指针变量并访问存储在地址中的值。

&运算符 称为地址运算符,用于返回变量的地址或将变量的地址访问指针

new 函数

  • new 是内建函数,函数原型为
func new(Type) *Type

  The new build-in function allocates memory(仅仅分配空间). The first argument is a type, not a value, and the value returned is a pointer to a newly allocated zero value of that type.内置函数 new 分配空间。传递给new 函数的是一个类型,不是一个值。返回值是 指向这个新分配的零值的指针

多重赋值:

  允许同时更新多个变量的值。在赋值之前,赋值语句右边的所有表达式将会先进行求值,然后再统一更新左边对应变量的值

有些表达式会产生多个值,比如调用一个有多个返回值的函数。当这样一个函数调用出现在元组赋值右边的表达式中时(译注:右边不能再有其它表达式),左边变量的数目必须和右边一致

作用域:

  声明语句的作用域对应的是一个源代码的文本区域;它是一个编译时的属性。一个变量的生命周期是指程序运行时变量存在的有效时间段,在此时间区域内它可以被程序的其他部分引用;是一个运行时的概念。

基本数据:

字符串

unicode是信源编码,对字符集数字化;所有的字符和码位(数字)建立了对应关系
utf8是信道编码,为更好的存储和传输。

常量

  常量是一种表达式,其保证在编译的时候计算出表达式的值,每种常量的潜在类型都是基础类型:boolean、string或数字。

  常量间的所有算术运算、逻辑运算和比较运算的结果也是常量,对常量的类型转换操作或以下函数调用都是返回常量结果:len、cap、real、imag、complex和unsafe.Sizeof

如果是批量声明的常量,除了第一个外其它的常量右边的初始化表达式都可以省略,如果省略初始化表达式则表示使用前面常量的初始化表达式写法,对应的常量类型也一样的。例如:

const (
    a = 1
    b
    c = 2
    d
)

fmt.Println(a, b, c, d) // "1 1 2 2"

常量声明可以使用iota常量生成器初始化,它用于生成一组以相似规则初始化的常量,但是不用每行都写一遍初始化表达式。在一个const声明语句中,在第一个声明的常量所在的行,iota将会被置为0,然后在每一个有常量声明的行加一

下面是来自time包的例子,它首先定义了一个Weekday命名类型,然后为一周的每天定义了一个常量,从周日0开始。在其它编程语言中,这种类型一般被称为枚举类型。

type Weekday int

const (
    Sunday Weekday = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)

周日将对应0,周一为1,如此等等。

 

数组

在数组字面值中,如果在数组的长度位置出现的是“...”省略号,则表示数组的长度是根据初始化值的个数来计算。因此,上面q数组的定义可以简化为

q := [...]int{1, 2, 3}
fmt.Printf("%T\n", q) // "[3]int"

for 和 range

除了for  Go 语言引入了另一个关键字 range 帮助我们快速遍历数组、切片、哈希表以及 Channel 等集合类型

  1. 初始化循环的 Ninit
  2. 循环的继续条件 Left
  3. 循环体结束时执行的 Right
  4. 循环体 NBody
for Ninit; Left; Right {
    NBody
}
hash := map[string]int{
        "1": 1,
        "2": 2,
        "3": 3,
    }
    for k, v := range hash {
        println(k, v)
    }

    分析遍历数组和切片清空元素的情况;
    分析使用 for range a {} 遍历数组和切片,不关心索引和数据的情况;
    分析使用 for i := range a {} 遍历数组和切片,只关心索引的情况;
    分析使用 for i, elem := range a {} 遍历数组和切片,关心索引和数据的情况;

SELECT:

  Go 语言中的 select 也能够让 Goroutine 同时等待多个 Channel 可读或者可写,在多个文件或者 Channel状态改变之前,select 会一直阻塞当前线程或者 Goroutine。

  select 是与 switch 相似的控制结构,与 switch 不同的是,select 中虽然也有多个 case,但是这些 case 中的表达式必须都是 Channel 的收发操作

  C 语言的 select 系统调用可以同时监听多个文件描述符的可读或者可写的状态,Go 语言中的 select 也能够让 Goroutine 同时等待多个 Channel 可读或者可写,在多个文件或者 Channel状态改变之前,select 会一直阻塞当前线程或者 Goroutine

  select 是与 switch 相似的控制结构,与 switch 不同的是,select 中虽然也有多个 case,但是这些 case 中的表达式必须都是 Channel 的收发操作

当我们在 Go 语言中使用 select 控制结构时,会遇到两个现象:

  1. select 能在 Channel 上进行非阻塞的收发操作;
  2. select 在遇到多个 Channel 同时响应时,会随机执行一种情况;

在通常情况下,select 语句会阻塞当前 Goroutine 并等待多个 Channel 中的一个达到可以收发的状态。但是如果 select 控制结构中包含 default 语句,那么这个 select 语句在执行时会遇到以下两种情况:

  1. 当存在可以收发的 Channel 时,直接处理该 Channel 对应的 case
  2. 当不存在可以收发的 Channel 时,执行 default 中的语句;

   Go 语言设计的这个现象很合理。select 的作用是同时监听多个 case 是否可以执行,如果多个 Channel 都不能执行,那么运行 default 也是理所当然的。

select 在遇到多个 <-ch 同时满足可读或者可写条件时会随机选择一个 case 执行其中的代码。

 

select 与 switch 原理很相似,但它的使用场景更特殊,学习了本篇文章,你需要知道如下几点区别:

  1. select 只能用于 channel 的操作(写入/读出/关闭),而 switch 则更通用一些;

  2. select 的 case 是随机的,而 switch 里的 case 是顺序执行;

  3. select 要注意避免出现死锁,同时也可以自行实现超时机制;

  4. select 里没有类似 switch 里的 fallthrough 的用法;

  5. select 不能像 switch 一样接函数或其他表达式。

 

posted @ 2020-09-04 23:01  codestacklinuxer  阅读(174)  评论(0编辑  收藏  举报