golang语言 内置函数、控制流

 

len 和 cap

调用     实参类型     结果

len(s)      [n]T, *[n]T         数组长度(== n)

       []T          切片长度

       chan T        信道缓存中元素队列的长度

       map[K]T     映射长度(已定义键的数量)

            string type          字符串的字节长度

cap(s)       [n]T, *[n]T         数组长度(== n)

            []T          切片容量

           chan T         信道缓存容量

s为 nil 值的切片、映射或信道,len(s)==0

s为 nil 值的切片或信道,cap(s)==0。

 s 为字符串常量,则表达式 len(s) 即为 常量  s 的类型为数组或数组指针,且表达式 s 不包含信道接收 或函数调用,则表达式 len(s) 与 cap(s) 即为常量,在这种用情况下, s 不会被求值。否则,len 与 cap 的调用不为常量,且 s 会被求值。

const (

  c1 = imag(2i) // imag(2i) = 2.0 is a constant

  c2 = len([10]float64{2}) // [10]float64{2} contains no function calls

  c3 = len([10]float64{c1}) // [10]float64{c1} contains no function calls

  c4 = len([10]float64{imag(2i)}) // imag(2i) is a constant and no function call is issued

  c5 = len([10]float64{imag(z)}) // invalid: imag(z) is a (non-constant) function call

  c6 = len([10]float64{x}) // 10

)

var z complex128

var x float64 = 3.0

new

type S struct { a int; b float64 }

new(S) 将动态分配内存、初始化为零值(a=0,b=0.0)并返回类型为 *S 的包含内存地址的值。

var p *[]int = new([]int) // p != nil *p == nil,没有底层数组

p := *new([]int) // p == nil

new(File) 和 &File{} 是等价的

make

切片、映射与信道为无需使用 new 来间接额外分配的引用类型。内建函数 make 接受的类型 T 必须为切片、映射或信道类型,可选地跟着一个特殊类型的表达式列表。它返回类型为 T (而非 *T)的值。其内存用零值来初始化。

调用         类型 T      结果

make(T, n)     slice         类型为T,长度为n,容量为n的切片

make(T, n, m)     slice         类型为T,长度为n,容量为m的切片

make(T)         map         类型为T的映射

make(T, n)     map         类型为T,初始空间为n个元素的映射

make(T)        channel         类型为T的同步信道

make(T, n)          channel      类型为T,缓存大小为n的异步信道

s := make([]int, 10, 100) // len(s) == 10,cap(s) == 100 的切片

c := make(chan int, 10) // 缓存大小为10的信道

m := make(map[string]int, 100) // 初始空间为100个元素的映射

n必须为能表示为int的值,若 n 在运行时为负值或大于 m, 就会引发panic

 

复数操作

complex(realPart, imaginaryPart floatT) complexT

real(complexT) floatT

imag(complexT) floatT

若这些函数的操作数均为常量,则返回值亦为常量

z == complex( real(z), imag(z) )

var a = complex(2, -2) // complex128

const b = complex(1.0, -1.4) // untyped complex constant 1 - 1.4i

x := float32(math.Cos(math.Pi/2)) // float32

var c64 = complex(5, -x) // complex64

var s int = complex(1, 0) // untyped complex constant 1 + 0i can be converted to int

_ = complex(1, 2<<s) // illegal: 2 assumes floating-point type, cannot shift

var rl = real(c64) // float32

var im = imag(a) // float64

const c = imag(b) // untyped constant -1.4

_ = imag(3 << s) // illegal: 3 assumes complex type, cannot shift

for

任何For子句的元素都可为空,但除非只有一个条件,否则分号是必须的。 若缺少条件,则它等价于 true。

for cond 等价于 for ; cond ;

for true 等价于 for ; true ; 等价于 for 等价于 for ; ;

for a := 0 ; ; { // 这个a被声明在外层隐式代码块中

  a := a // 内层显式代码块

}

range

range右边部分叫做range表达式,

range表达式如果不是信道,那么for i , _ := range s 等价于 for i := range s,

range表达式如果是信道,左边只能有一个值

for语句之外声明的迭代变量,其值为最后一次迭代的值

for range ch {} // 排空一个channel

for range str {cnt++} // 统计unicode字符

for i, v := range arr { // arr会复制

  a := 3

  fmt.Println(&i, &v, &a) // i 和 v 的地址不变,a地址会变

}

x是数组、数组指针或切片,第一个迭代变量是下标,从0开始递增到 len(x)-1,

  nil值的切片会迭代0次,

  nil值的数组指针,若第二个迭代变量被忽略或舍弃,迭代 len(数组) 次,否则panic

x是字符串,第一个迭代变量是当前unicode码点第一个字节的下标,

  第二个迭代变量是rune类型的unicode码点值,

  若遇到无效的unicode码点,第一个迭代变量下次加1,第二个迭代变量为0xFFFD,

x是map,迭代顺序随机,map为nil迭代次数为0,

  迭代时删除了未迭代到的项,该项之后不会被迭代到

  迭代时创建的新项可能会被迭代,也可能不会

x是信道,会迭代到信道被关闭,nil值的信道会一直阻塞

if

a := 0

if a := 1; ... { // 外层隐式代码块 可选的初始化语句,只能有一句

  a := 2 // 内层显式代码块

  fmt.Println(a) // 2

}else if b := 2; ... { // else if 也可以初始化 并且可以再次初始化a

  fmt.Println(a) // 1

}

fmt.Println(a) // 0

func Foo() (err error) {

  if err := Bar(); err != nil { return  } // 局部变量屏蔽了命名返回值

  return 

}

switch

接受可选的初始化语句

没有条件的switch相当于switch true,

没有分支的switch是个空操作

case 可以为变量、表达式或函数,可以用逗号分隔,

执行到当前case时才会去求case的值,否则跳过

默认不会执行下一个case,fallthrough表示执行下一个case,最后一个分支不能有fallthrough,fallthrough必须为分支内的最后一条语句,if true { fallthrough }是非法的

最多只能有一个default,可以出现在任何位置。 能fallthrough 进/出 default

switch表达式要有确定的类型,所以不能switch nil

switch 1 case int8(1) //报错 目测是switch 1确定了1的类型

switch int8(1) case 1 //ok 目测是case1没有确定1的类型

switch int8(1) case int(1) //报错

 

标签语句

可作为 goto、break 或 continue 语句的目标,标签语句至少要被使用一次

goto

可在标签的前面或后面,但不能在标签所处的代码块之外,

也不能在变量声明之前,goto到该变量的作用域里,例如

goto A

a := 1

A:

break

用于for、switch、select中

OuterLoop:

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

  for j = 0; j < m; j++ {

    switch a[i][j] {

    case item:

      break OuterLoop // 跳出OuterLoop后面的for循环

    }

  }

}

continue

用于for中

RowLoop:

for y, row := range rows {

  for x, data := range row {

    continue RowLoop

  }

}

猜你喜欢

转载自www.cnblogs.com/ts65214/p/12976972.html