GO学习笔记之表达式

这篇具有很好参考价值的文章主要介绍了GO学习笔记之表达式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

保留字

Go语言仅25个保留关键字(keyword),这是最常见的宣传语,虽不是主流语言中最少的,但也确实体现了Go语法规则的简洁性。保留关键字不能用作常量、变量、函数名,以及结构字段等标识符。

break   default    func   interface select
case    defer      go    map   struct
chan    else   goto   package    switch
const   fallthrough if    range      type
continue for   import     return       var

相比在更新版本中不停添加新语言功能,我更喜欢简单的语言设计。某些功能可通过类库扩展,或其他非侵入方式实现,完全没必要为了“方便”让语言变得臃肿。过于丰富的功能特征会随着时间的推移抬升门槛,还会让代码变得日趋“魔幻”,降低一致性和可维护性。

运算符

很久以前,流传“程序=算法+数据”这样的说法。
算法是什么?通俗点说就是“解决问题的过程”。小到加法指令,大到成千上万台服务器组成的分布式计算集群,抛去抽象概念和宏观架构,最终都由最基础的机器指令过程去处理不同层次存储设备里的数据。

学习语言和设计架构不同,我们所关心的就是微观层次,诸如语法规则所映射的机器指令,以及数据存储位置和格式等等。其中,运算符和表达式用来串联数据和指令,算是最基础的算法。
另有一句话:“硬件的方向是物理,软件的结局是数学。”
全部运算符及分隔符列表:

+      &       +=      &=       &&      ==      !=      (      ) 
-      |       -=      |=       ||      <       <=      [      ] 
*      ^       *=      ^=       <-      >       >=      {      } 
/      <<      /=      <<=      ++      =       :=      ,      ; 
%      >>      %=      >>=      --      !       ...     .      : 
       &^              &^=

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

优先级

一元运算符优先级最高,二元则分成五个级别,从高往低分别是:
highest * / % << >> & &^ + - | ^ == != < <= > >= && lowest ||

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

二元运算符

除位移操作外,操作数类型必须相同。如果其中一个是无显式类型声明的常量,那么该常量操作数会自动转型。

func main() { 
   const v=20            // 无显式类型声明的常量 
  
   var a byte=10
   b:=v+a                 //v自动转换为byte/uint8类型 
   fmt.Printf("%T, %v\n",b,b) 
   const c float32=1.2
   d:=c+v         //v自动转换为float32类型 
   fmt.Printf("%T, %v\n",d,d) 
}
uint8,30
float32,21.2
func main() { 
   b:=23            //b是有符号int类型变量 
   x:=1<<b     // 无效操作:1<<b(shift count type int,must be unsigned integer) 
   println(x) 
}

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

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

func main() { 
   a:=1.0<<3           // 常量表达式(包括常量展开) 
   fmt.Printf("%T, %v\n",a,a)       //int,8
  
   var s uint=3
   b:=1.0<<s           // 无效操作:1<<s(shift of type float64) 
   fmt.Printf("%T, %v\n",b,b)       // 因为b没有提供类型,那么编译器通过1.0推断, 
                       // 显然无法对浮点数做位移操作 
   var c int32=1.0<<s       // 自动将1.0转换为int32类型 
   fmt.Printf("%T, %v\n",c,c)       //int32,8
}

位运算符

二进制位运算符比较特别的就是“bit clear”,在其他语言里很少见到。

AND          按位与:都为1     a&b  0101&0011=0001
OR           按位或:至少一个1   a|b  0101|0011=0111
XOR          按位亦或:只有一个1     a^b  0101^0011=0110
NOT          按位取反   (一元)        ^a ^0111=1000
AND NOT      按位清除   (bit clear)  a&^b 0110&^1011=0100
LEFT SHIFT    位左移           a<<2 0001<<3=1000
RIGHT SHIFT       位右移           a>>2 1010>>2=0010

位清除(AND NOT)和位亦或(XOR)是不同的。它将左右操作数对应二进制位都为1的重置为0(有些类似位图),以达到一次清除多个标记位的目的。

const( 
   read  byte=1<<iota
   write
   exec
   freeze
) 
  
func main() { 
   a:=read|write|freeze
   b:=read|freeze|exec
   c:=a&^b     // 相当于a^read^freeze,但不包括exec
  
   fmt.Printf("%04b&^ %04b= %04b\n",a,b,c) 
}

自增

自增、自减不再是运算符。只能作为独立语句,不能用于表达式。

指针

不能将内存地址与指针混为一谈。
内存地址是内存中每个字节单元的唯一编号,而指针则是一个实体。指针会分配内存空间,相当于一个专门用来保存地址的整型变量。

                    p:= &x                x:=100
    -----------------+--------+------\\-------+------+--------- 
    memory ...     |0x1200|     ....      |100 |   ... 
    -----------------+--------+------\\-------+------+--------- 
    address       0x800                  0x1200

取址运算符“&”用于获取对象地址。
指针运算符“”用于间接引用目标对象。
二级指针**T,如包含包名则写成
package.T。
并非所有对象都能进行取地址操作,但变量总是能正确返回(addressable)。指针运算符为左值时,我们可更新目标对象状态;而为右值时则是为了获取目标状态。

func main() { 
   x:=10
  
   var p*int= &x     // 获取地址,保存到指针变量 
    *p+=20           // 用指针间接引用,并更新对象 
  
   println(p, *p)       // 输出指针所存储的地址,以及目标对象 
}


输出
0xc82003df30 30

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

func main() { 
   x:=10
   p:= &x
  
   p++                    // 无效操作:p++ (non-numeric type*int) 
   var p2*int=p+1  // 无效操作:p+1(mismatched types*int and int) 
  
   p2= &x
   println(p==p2) 
}

可通过unsafe.Pointer将指针转换为uintptr后进行加减法运算,但可能会造成非法访问。
Pointer类似C语言中的void*万能指针,可用来转换指针类型。它能安全持有对象或对象成员,但uintptr不行。后者仅是一种特殊整型,并不引用目标对象,无法阻止垃圾回收器回收对象内存。
指针没有专门指向成员的“->”运算符,统一使用“.”选择表达式。

func main() { 
   a:=struct{ 
       x int
    }{} 
  
   a.x=100
  
   p:= &a
   p.x+=100      // 相当于p->x+=100
  
   println(p.x) 
}

零长度(zero-size)对象的地址是否相等和具体的实现版本有关,不过肯定不等于nil。即便长度为0,可该对象依然是“合法存在”的,拥有合法内存地址,这与nil语义完全不同。
在runtime/malloc.go里有个zerobase全局变量,所有通过mallocgc分配的零长度对象都使用该地址。不过上例中,对象a、b在栈上分配,并未调用mallocgc函数。

func main() { 
   var a,b struct{} 
  
   println(&a, &b) 
   println(&a== &b, &a==nil) 
}


运行结果:

0xc820041f2f 0xc820041f2f
true false文章来源地址https://www.toymoban.com/news/detail-478182.html

到了这里,关于GO学习笔记之表达式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring表达式语言(SPEL)学习(03)

    在表达式中直接写name和getName(),这时候Expression是无法解析的,因为其不知道name和getName()对应什么意思 当表达式是基于某一个对象时,我们可以把对应的对象作为一个rootObject传递给对应的Experssion进行取值 通过指定EvaluationContext我们可以让name和getName()变得有意义,指定了Ev

    2024年02月02日
    浏览(37)
  • 学习笔记整理-正则表达式-01-认识正则

    1. 什么是正则表达式 正则表达式(regular expression)描述了字符串\\\"构成模式\\\",经常被用于检查字符串是否符合预定的格式要求。 用一个例子快速演示正则表达式基本使用方法: 检查某个字符串是否是6位数字 /^d{6}$/ 就是正则表达式,它描述了字符串必须是\\\"6位数字\\\"的构成规则。

    2024年02月12日
    浏览(32)
  • Python学习笔记_基础篇(八)_正则表达式

    1.1. 简单介绍 正则表达式并不是Python的一部分。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大。得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是一样的,区别只

    2024年02月12日
    浏览(36)
  • 初始Go语言2【标识符与关键字,操作符与表达式,变量、常量、字面量,变量作用域,注释与godoc】

      go变量、常量、自定义类型、包、函数的命名方式必须遵循以下规则: 首字符可以是任意Unicode字符或下划线。 首字符之外的部分可以是Unicode字符、下划线或数字。 名字的长度无限制。 理论上名字里可以有汉字,甚至可以全是汉字,但实际中不要这么做。 Go语言

    2023年04月09日
    浏览(35)
  • go 正则表达式

    A regular expression is a useful feature in a programming language to check whether or not the string contains the desired value. It can not only check but also extract the data from the string. In this post, we’ll go through the basic usage of regexp . Let’s start with an easy example. The first one only checks if the value is contained in a string. reg

    2024年02月11日
    浏览(31)
  • Python学习笔记:正则表达式、逻辑运算符、lamda、二叉树遍历规则、类的判断

    序号 实例 说明 1 . 匹配任何字符(除换行符以外) 2 d 等效于[0-9],匹配数字 3 D 等效于[^0-9],匹配非数字 4 s 等效于[trnf],匹配空格字符 5 S 等效于[^trnf],匹配非空格字符 6 w 等效于[A-Za-z0-9],匹配单字字符 7 W 等效于[^A-Za-z0-9],匹配非单字字符 8 [ab]cdef 匹配acdef或bcd

    2024年02月11日
    浏览(51)
  • Go中常用的表单验证(正则表达式)

     对于性能要求很高的用户来说,这是一个老生常谈的问题了,他们认为应该尽量避免使用正则表达式,因为使用正则表达式的速度会比较慢。但是在目前机器性能那么强劲的情况下,对于这种简单的正则表达式效率和类型转换函数是没有什么差别的。如果你对正则表达式很

    2024年02月13日
    浏览(39)
  • Go语句与表达式深度解析:全案例手册

    关注公众号【TechLeadCloud】,分享互联网架构、云服务技术的全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。 语句是Go编程

    2024年02月09日
    浏览(33)
  • 【Go】Go 文本匹配 - 正则表达式基础与编程中的应用 (8000+字)

             本文共计8361字,预计阅读时间18分钟         正则表达式(Regular Expression, 缩写常用regex, regexp表示)是计算机科学中的一个概念,很多高级语言都支持正则表达式。 目录 何为正则表达式 语法规则 普通字符 字符转义 限定符 定位符 分组构造 模式匹配 regexp包

    2024年02月12日
    浏览(31)
  • Spring:表达式语言

    Spring 表达式(Spring EL) 是一种功能强大的表达式语言,以 #{ 表达式 } 作为定界符,用于在运行时对对象进行访问和操作。通过使用 Spring 表达式达到简化开发、减少逻辑或配置的编写的目的。 Spring EL 主要可以引用 bean ,调用其属性和方法,也可以在 bean 标签中使用 value 属

    2024年02月16日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包