• 周四. 6 月 20th, 2024

    Go语言表达式

    root

    10 月 13, 2019 #Golang

    3.2 运算符

    除位移操作外,操作数类型必须相同。如果其中一个是无显式类型声明的常量,那么该常量操作数会自动转型。
    位移右操作数必须是无符号整数,或可以转换的无显式类型常量
    自增,自减不再是运算符。只能作为独立的语句,不能用于表达式
    func main() {
        a := 1
        ++a //语法错误。unexpected ++ (不能前置)
        if (a++) > 1 {  //语法错误: unexpected++, expecting) 语句不能作为表达式使用
        p := &a
        *p++    //相当于(*p)++
        println(a)
        }
    }
    
    指针: 不能将内存地址与指针混为一谈
    内存地址是内存中每个字节单元的唯一编号,而指针则是一个实体。指针会分配内存空间,相当于一个专门用来保存地址的整型变量
    • &用于获取对象地址
      • 间接引用目标对象
    • 二级指针*T,如包含包名则写成package.T
    可通过unsafe.Pointer将指针转换为uintptr后进行加减法远算。但可能会造成非法访问.
    Pointer类似C语言中的void*万能指针,可用来转换指针类型。它能安全持有对象或对象成员,但uintptr不行。后者仅是一种特殊类型,并不引用目标对象,无法阻止垃圾回收器回收对象内存

    3.3 初始化

    对复合类型(数组,切片,字典,结构体)变量初始化时,有一些语法限制
    • 初始化表达式必须含类型标签
    • 左花括号必须在类型尾部,不能另起一行
    • 多个成员初始值以逗号分隔
    • 允许多行,但每行须以逗号或右花括号结束
    正确示例
    type data struct {
        x int
        s string
    }
    var a data = data{1, "abc"}
    
    b := data {
        1, 
        "abc",
    }
    
    c := []int {
        1, 
        2 }
    
    d := []int{1, 2,
        3, 4,
        5,
    }
    

    3.4 流控制

    if…else…
    if x > 5 {
        println("a")
    } else if x < 5 && x > 0 {
        println("B")
    } else {
        println("z")
    }
    
    if xinit(); x==0 {  //优先执行xinit函数
        println("a")
    }
    
    if a, b := x+1, x+10; a<b { //定义一个或多个局部变量
        println(a)
    } else {
        println(b)
    }
    
    死代码是指永远不会被执行的代码,可使用专门的工具,或用代码覆盖率(code coverage)测试进行检查。
    switch
    func main() {
        a, b, c, x := 1, 2, 3, 2
        switch x {
            case a, b:  //多个匹配条件命中其一即可(OR),变量
                println("a | b")
            case c:
                println("c")
            case 4:
                println("d")
            default:
                println("z")
        }
    }
    
    相邻的空case不构成多条件匹配
    switch x {
        case a: //单条件, 内容为空。隐式"case a: break;"
        case b:
            println("b")
    }
    
    不能出现重复的case常量值
    无须显式执行break,如须贯通后续case须执行fallthrough,但不再匹配后续条件表达式
    fallthrough必须放在case块结尾,可使用break语句阻止.
    for
    for i:=0; i<3; i++ {
        
    }
    for x<10 {
        
    }
    for {
        
    }
    
    for…range完成数据迭代,支持字符串,数组,数组指针,切片,字典,通道类型,返回索引,键值数据
    注意, range会复制目标数据。受直接影响的是数组,可改用数组指针或切片类型
    func main() {
        data := [3]int{10, 20, 30}
        for i, x := range data {            //从data复制品中取值
            if i == 0 {
                data[0] += 100
                data[1] += 200
                data[2] += 300
            }
            fmt.Printf("x:%d, data:%d\n", x, data[i])
        }
        for i, x := range data[:] {  //仅复制slice,不包括底层array
             if i == 0 {
                data[0] += 100
                data[1] += 200
                data[2] += 300
            }
            fmt.Printf("x:%d, data:%d\n", x, data[i])
        }
    }
    
    建议嵌套循环不要超过2层,否则会难以维护。必须时可剥离,重构为函数。
    goto,continue,break
    使用goto前,须先定义标签。标签区分大小写,且未使用的标签会引发编译错误
    func main() {
        start:      //label start defined and not used
            for i:=0; i<3; i++ {
                println(i)
                if i>1 {
                    goto exit
                }
            }
        exit:
            println("exit.")
    }
    
    break; 用于switch,for,select语句,终止整个语句块执行
    continue; 仅用于for循环,终止后续逻辑,立即进入下一轮循环

    root

    发表回复