首页 > 其他分享 >Study for Go ! Chapter two - Expression

Study for Go ! Chapter two - Expression

时间:2023-03-03 21:13:55浏览次数:46  
标签:Chapter 语句 Study 运算符 switch Go 执行 表达式 指针

Study for Go ! Chapter two - Expression

1. Keyword

 

 

 

  • Golang仅有 25 个保留关键字,体现了 golang 语法规则的简洁性

  • 保留关键字不能用作常量、变量、函数名、以及结构字段等标识符

 

2. Operator

 

 

 

  • Golang 中没有乘幂和绝对值运算符,对应的是标准库 math 里的 Pow、Abs 函数实现

  • 一元运算符的优先级最高

  • 二元运算符有五个级别从高到低分别是:

 

 

 

  • 相同优先级的二元运算符,从左到右依次计算

  • 使用二元运算符,除了位移操作以外,操作数类型必须相同,如果其中一个是无显式类型声明的常量,那么该常量操作数会自动转型

  • 位移右操作数必须是无符号整数,或者可以转换的无显式类型常量

  • 如果是非常量位移表达式,那么会优先将无显式类型的常量左操作数转型

  • 位运算符

     

     

     

Attention:

  • 在 golang 中自增、自减不再是运算符,而是作为独立语句存在,不能用于表达式使用

  • 表达式通常式 求值代码,可以作为右值或者参数使用,而语句完成一个行为,比如 if、 for 代码块,表达式可以作为语句使用,但是语句却不能当作表达式

Pointer:

  • 不能将内存地址与指针混为一谈

  • 内存地址是内存中每个字节单元的唯一编号,而指针则是一个实体

  • 指针会被分配内存空间,相当于一个专门用来保存地址的整型变量

  • 取值运算符 “ & ” 用于获取对象地址

  • 指针运算符 “ * ” 用于间接引用目标对象

  • 二级指针 **T, 如果包含包名则写成 *package.T

  • 并非所有对象都能进行取地址操作,但是变量总是能够正确返回 (addressable),指针运算符为左值时,我们可更新目标对象状态,为右值时,我们可以获取目标对象状态

  • 指针支持相等运算符,但不能做加减法运算和类型转换,如果两个指针指向同一地址,或者都为nil,那么它们相等

Attention:

  • 可以通过 unsafe.Pointer 将指针转换为 uintptr 后进行加减法运算,但可能会导致非法访问

  • Pointer 类似C 语言中的 void* 万能指针, 可以用来转换指针类型。他能安全持有对象和对象成员,但是 uintptr 不行。uintptr 仅是一种特殊类型, 并不用于目标对象, 无法组织垃圾回收器回收对象内存

  • Golang 中没有专门指向成员的 " -> " 运算符, 统一使用 “ . ” 选择表达式

Zero - size

  • 零长度 (zero - size)对象的地址是否相等和具体的实现版本有关,但是肯定不等于 nil

  • 即使长度为 0 ,可该对象依然时合法存在的,拥有合法的内存地址,这与 nil 语义完全不同

  • 在 runtime/malloc.go 里有个 zerobase 全局变量, 所有通过 mallocgc 分配的零长度对象都使用该地址

 

3. Initialization

  • 对复合类型(slice、array、map、struct)变量初试化时,有一些语法限制

  1. 初始化表达式必须包含类型标签

  2. 左花括号必须在类型尾部,不能另起一行

  3. 多个成员初始值以逗号分割

  4. 允许多行,但每行以逗号或者右花括号结束

 

4. Flow Control

  • Golang 精简(合并)了流控制语句,虽然某些时候不够便捷,但是够用

    1. if...else...

      • 条件表达式值必须是 bool 类型,可以省略括号,但是左花括号不能另起一行

      • 支持初始化语句,可定义块局部变量或执行初始化函数

        Attention:

         

         

上示例中,if 块承担了两种逻辑:错误处理和后续正常操作。

基于重构原则,我们应该保持代码块功能的单一性

 

 

如此,if 块仅完成条件检查和错误处理,相关正常逻辑保持在同一层次。

这样做便于代码的阅读,也提升了代码的可维护性,更利于拆分重构

如果需要在多个条件块中使用局部变量,那么只能保留原层次,或者直接使用外部变量

对于某些过于复杂的组合条件,建议将其重构为函数

函数调用虽然有一些性能损失,但是却让主流程变得更加清爽,更易于测试,改善代码 可维护性

 

Notice

将流程和局部细节分离是一个很好的习惯

不同的变化因素被分隔在各自独立单元(函数或者模块)内,可以避免修改时造成关联错误,减少患“ 肥胖症 ”的函数数量

 

  1. switch

  • 条件表达式支持非常量值,使得 golang 比C更加灵活。相比于if表达式, switch值列表更加简洁

  • 编译器对if、switch 生成的机器指令可能完全相同,所谓谁的性能更好看具体情况而定

  • switch 同样支持初始化语句,按照从上到下,从左到右匹配case执行,只有全部匹配失败时才会执行default块

  • 无需显式执行 break 语句, case执行完毕后自动中断,如要继续访问后续 case (源码顺序),需要执行 fallthrough 关键字,但是不再进行条件表达式匹配

    Attention:

    • fallthrough 必须放在 case 块的结尾,可被 break 语句阻止

    • 如果 fallthrough 放在 default 后面,因为会按照源码执行顺序执行所以不会执行 default 导致错误

     

    Notice:

    • 某些时候,switch 被用来替换 if 语句, 被省略的 switch 条件表达式默认为 true,继而与 case 比较表达式结果匹配

    • switch 有时候也用于接口类型匹配

  1. for

  • golang 中仅有 for 这一种循环语句

  • 初始化语句仅能被执行一次,条件表达式中如果有函数调用,要先确认是否会被重复执行

  • 如果存在重复执行的函数,则可能会被编译器优化掉,也可能是动态结果须每次执行确认

  • 处理上述问题的办法是,创建临时变量保存该函数结果

  • 使用 for...range 完成数据迭代支持 string、array、pointer、array pointer、slice、map、channel等类型,返回索引、键值数据

  • 允许返回单指(次数),或用 “ _ ” 忽略

  • 无论是 for 还是 for...range 迭代,其中定义的局部变量都会被重复使用(地址相同),但这样会对闭包有一些影响

    Attention

    • 使用 range 时会先复制要迭代的目标数据,再在复制体中区取值,所以会影响数组的 range 使用因此建议使用数组指针或者切片类型去代替

    • 在 range 的复制问题中,string、slice 的基本结构都是很小的结构体,而 map、channel 本身时指针封装,它们的复制成本都很小,无须专门优化

    • 如果 range 的目标表达式时函数调用,那也仅被执行一次

  1. goto、continue、break

  • 使用 goto 前,需要先定义标签。标签区分大小写,且未使用的标签会引发编译错误

  • 不能使用 goto 跳转到其他函数或者内层代码块内

  • break 和 continue 用于终端代码块的执行

 

 

 

  • 配合标签, break 和 continue 可以在多层嵌套中 指定目标层级

 

标签:Chapter,语句,Study,运算符,switch,Go,执行,表达式,指针
From: https://www.cnblogs.com/slowlydance2me/p/17176981.html

相关文章

  • go day200
    结构体变量的赋值点击查看代码packagemainimport"fmt"typeStustruct{ Namestring Ageint}funcmain(){ //方式一:在创建结构体变量时,直接指定字段......
  • MongoDB写入数据策略
    上篇文章介绍了Mongo读取数据的策略(MongoDB读数据策略),主要是readconcern、readpreference两参数,其中readconcern作用于服务端,决定了什么时候能读取到数据;readpreference在客......
  • Wire:Go最优雅的依赖注入工具
    阅读用时:4分钟导语“成熟的工具,要学会自己写代码”。本文介绍了Go依赖注入工具[[Wire]]及其使用方法,以及在实践中积累的各种运用技巧。当代码达到一定规模后,[[Wire]......
  • 敏捷工具leangoo领歌时间线视图上线啦
    https://www.leangoo.com/17735.htmlLeangoo企业版新增「时间线视图」,通过「时间线视图」你可以在项目管理中非常直观的了解每个人的工作分配及各个任务的排期,方便及时......
  • [Go语言tips04]二维数组与二维切片
    0.引言既然在Go语言中数组和切片同时存在并且是两个不同的类型,那当他们是二维时又会产生什么样的问题?因为数组和切片同时存在,在Go语言中二维的使用就会显得和别的语言很......
  • Go组件库总结之协程睡眠唤醒
    本篇文章我们用Go封装一个利用gopark和goready实现协程睡眠唤醒的库。文章参考自:https://github.com/brewlin/net-protocol1.gopark和goready的声明//go:linknamegopark......
  • protobuf golang&&python序列化反序列化测试
    1.概要最近考虑采用protobuf来实现kafka消息传递,所以先测试一下golang和python之前序列化互通问题。由于go和python对于二进制的表示在ide层面是无法统一的,直接把python......
  • Django+vue 上传execl文件并解析
    Django+vue上传execl文件并解析VUE<template><el-buttontype="primary"class="but_list_but1"><inputtype="file"name="avatar"id="avatar"style="display......
  • Study for Go! Chapter one - Type
    StudyforGo!-Type1.Variable关键字为"var"自动初始化为二进制零值编译器推测数据类型变量类型放在变量名之后可以一次性定义多个变量且可以是不同......
  • Gossip
    共识性算法GossipGossip也叫EpidemicProtocol(流行病协议),这个协议基于最终一致性以及去中心化设计思想。主要用于分布式节点之间进行信息交换和数据同步,这种场景的一......