当前位置: 首页 > news >正文

Go语言运算符全解析

基本运算符

算术运算符

  • + 加法

    • 数值相加:3 + 5 结果为 8
    • 字符串拼接:"Hello" + " " + "World" 结果为 "Hello World"
    • 示例:sum := 10 + 20 // sum = 30
  • - 减法

    • a - b 计算两个数的差
    • 示例:diff := 15 - 7 // diff = 8
  • * 乘法

    • a * b 计算两个数的乘积
    • 示例:product := 3 * 4 // product = 12
  • / 除法

    • 整数除法会截断小数部分:5 / 2 = 2
    • 浮点数除法保留小数:5.0 / 2 = 2.5
    • 示例:quotient := 10 / 3 // quotient = 3
  • % 取模

    • 求余数:5 % 2 = 1
    • 示例:remainder := 10 % 3 // remainder = 1
  • ++ 自增

    • 只能作为语句:i++
    • 不能作为表达式:x = i++ 是非法语法
    • 示例:
      i := 0
      i++ // i = 1
      

  • -- 自减

    • 只能作为语句:i--
    • 示例:
      j := 5
      j-- // j = 4
      

关系运算符

  • == 等于

    • 比较两个值是否相等:a == b
    • 示例:isEqual := (10 == 10) // isEqual = true
  • != 不等于

    • 示例:isNotEqual := (10 != 5) // isNotEqual = true
  • > 大于

    • 示例:isGreater := (15 > 10) // isGreater = true
  • < 小于

    • 示例:isLess := (3 < 5) // isLess = true
  • >= 大于等于

    • 示例:isGE := (10 >= 10) // isGE = true
  • <= 小于等于

    • 示例:isLE := (5 <= 10) // isLE = true

逻辑运算符

  • && 逻辑与

    • 短路运算:false && expr 不计算右边表达式
    • 示例:
      if x > 0 && y < 10 {// 只有x>0且y<10都为真时才执行
      }
      

  • || 逻辑或

    • 短路运算:true || expr 不计算右边表达式
    • 示例:
      if x == 0 || y == 0 {// x等于0或y等于0时执行
      }
      

  • ! 逻辑非

    • 取反操作:!truefalse
    • 示例:
      isValid := false
      if !isValid {// 当isValid为false时执行
      }
      

位运算符

  • & 按位与

    • 示例:0b1010 & 0b1100 = 0b1000 (即 10 & 12 = 8)
  • | 按位或

    • 示例:0b1010 | 0b1100 = 0b1110 (即 10 | 12 = 14)
  • ^ 按位异或

    • 示例:0b1010 ^ 0b1100 = 0b0110 (即 10 ^ 12 = 6)
  • << 左移位

    • 示例:1 << 3 得 8 (二进制 0001 左移3位变为 1000)
  • >> 右移位

    • 示例:8 >> 2 得 2 (二进制 1000 右移2位变为 0010)
  • &^ 位清除(AND NOT)

    • 示例:0b1010 &^ 0b1100 = 0b0010 (即 10 &^ 12 = 2)

赋值运算符

  • = 基本赋值

    • 示例:x = 10
  • 复合赋值

    • +=x += 5 等价于 x = x + 5
    • -=x -= 3 等价于 x = x - 3
    • *=x *= 2 等价于 x = x * 2
    • /=x /= 4 等价于 x = x / 4
    • %=x %= 3 等价于 x = x % 3
    • <<=x <<= 1 等价于 x = x << 1
    • >>=x >>= 2 等价于 x = x >> 2
    • &=x &= 0xF 等价于 x = x & 0xF
    • ^=x ^= 0xFF 等价于 x = x ^ 0xFF
    • |=x |= 0x0F 等价于 x = x | 0x0F

特殊运算符

指针运算符

  • & 取地址

    • 获取变量内存地址:&x
    • 示例:
      x := 10
      ptr := &x // ptr现在保存x的内存地址
      

  • * 解引用

    • 访问指针指向的值:*ptr
    • 示例:
      x := 10
      ptr := &x
      fmt.Println(*ptr) // 输出10
      

通道运算符

  • <- 用于通道的发送和接收
    • 发送:ch <- value 将value发送到通道ch

      ch := make(chan int)
      go func() {ch <- 42 // 发送42到通道
      }()
      

    • 接收:value := <-ch 从通道ch接收值

      received := <-ch // 从通道接收值
      fmt.Println(received) // 输出42
      

类型断言运算符

  • .(type) 用于接口类型断言
    • 类型判断:

      var val interface{} = "hello"
      if s, ok := val.(string); ok {fmt.Println(s) // 输出"hello"
      }
      

    • 类型开关:

      switch v := x.(type) {
      case int:fmt.Println("int:", v)
      case string:fmt.Println("string:", v)
      default:fmt.Println("unknown type")
      }
      

内存分配运算符

  • new

    • 分配零值内存并返回指针:ptr := new(int)
    • 示例:
      p := new(int) // p是*int类型,指向的int值为0
      *p = 10       // 修改指针指向的值
      

  • make

    • 用于slice、map和channel的初始化
    • 示例:
      s := make([]int, 10)   // 长度10的slice
      m := make(map[string]int) // 空map
      ch := make(chan int, 5)   // 缓冲区大小5的通道
      

运算符优先级

优先级从高到低:

  1. * / % << >> & &^
  2. + - | ^
  3. == != < <= > >=
  4. &&
  5. ||

示例:

result := 5 + 3 * 2 // 结果为11,因为乘法优先级高于加法

优先级括号明确:

result := (5 + 3) * 2 // 结果为16,括号改变优先级

运算符重载

Go 语言不支持运算符重载。替代方案:

使用方法调用实现类似功能,例如实现 Add 方法代替 + 运算符:

type Vector struct { X, Y float64 }func (v Vector) Add(u Vector) Vector {return Vector{v.X + u.X, v.Y + u.Y}
}func main() {v1 := Vector{1, 2}v2 := Vector{3, 4}sum := v1.Add(v2) // 结果为Vector{4, 6}
}

实际应用示例

算术运算符

// 计算圆的面积
radius := 5.0
area := math.Pi * radius * radius
fmt.Printf("Area: %.2f\n", area) // 输出: Area: 78.54// 计算两点间距离
func distance(x1, y1, x2, y2 float64) float64 {dx := x2 - x1dy := y2 - y1return math.Sqrt(dx*dx + dy*dy)
}

位运算符优化

// 快速判断奇偶
isEven := num & 1 == 0  // 如果num是偶数则为true// 乘以2的幂次
result := num << 3 // 等同于 num * 8// 交换两个变量的值(不使用临时变量)
a, b := 10, 20
a ^= b
b ^= a
a ^= b // 现在a=20, b=10// 检查是否为2的幂次
isPowerOfTwo := n > 0 && (n & (n - 1)) == 0

通道运算符

// 并发处理多个任务
func worker(id int, jobs <-chan int, results chan<- int) {for j := range jobs {time.Sleep(time.Second) // 模拟耗时操作results <- j * 2}
}func main() {jobs := make(chan int, 100)results := make(chan int, 100)// 启动3个workerfor w := 1; w <= 3; w++ {go worker(w, jobs, results)}// 发送9个任务for j := 1; j <= 9; j++ {jobs <- j}close(jobs)// 收集结果for a := 1; a <= 9; a++ {fmt.Println(<-results)}
}

常见错误与陷阱

整数除法

a := 5 / 2 // 结果为2,不是2.5// 正确做法:
b := float64(5) / 2 // 2.5// 常见错误场景:
percentage := part / total * 100 // 如果part和total都是整数,结果可能为0
// 正确应为:
percentage := float64(part) / float64(total) * 100

逻辑短路

if p != nil && *p == 10 { // 安全访问指针,因为如果p为nil,不会执行*p
}// 错误示范:
if *p == 10 && p != nil { // 可能导致panic
}

nil 指针

var p *int
*p = 10 // 运行时panic,因为p是nil// 安全做法:
if p != nil {*p = 10
}// 或者使用new初始化:
p := new(int)
*p = 10 // 安全

优先级错误

if a == 1 || b == 2 && c == 3 { ... } 
// 实际解析为:a == 1 || (b == 2 && c == 3)
// 可能意图是:(a == 1 || b == 2) && c == 3// 正确做法是明确使用括号:
if (a == 1 || b == 2) && c == 3 { ... }

性能优化建议

位运算替代算术运算

// 用位运算代替乘除2的幂次
x = x << 1 // 代替 x * 2
x = x >> 1 // 代替 x / 2// 取模运算优化
remainder := x & (n-1) // 代替 x % n,当n是2的幂次时// 判断符号位
isNegative := x >> 31 // 对于32位整数

避免高开销运算符

// 减少不必要的浮点运算
// 错误示例:
for i := 0; i < n; i++ {x := float64(i) * 0.1 // 每次循环都做浮点转换
}// 优化为:
step := 0.1
for i := 0; i < n; i++ {x := float64(i) * step // 只做一次浮点转换
}// 避免频繁的内存分配
// 错误示例:
for i := 0; i < 1000; i++ {s := make([]byte, 1024) // 每次循环都分配新内存// 使用s...
}// 优化为:
buf := make([]byte, 1024)
for i := 0; i < 1000; i++ {// 重用buf// 使用buf...
}

编译器优化

// 使用常量表达式让编译器优化
const mask = 1<<10 - 1 // 编译时计算// 错误示例:
var mask = 1<<10 - 1 // 运行时计算// 循环展开优化
const size = 4
var sum int
for i := 0; i < size; i++ {sum += i
}
// 编译器可能会展开为:
sum = 0 + 1 + 2 + 3

通道操作优化

// 批量处理优于单次操作
// 低效:
for i := 0; i < 1000; i++ {ch <- i // 1000次通道操作
}// 优化为:
batch := make([]int, 1000)
for i := 0; i < 1000; i++ {batch[i] = i
}
ch <- batch // 1次通道操作// 合理设置通道缓冲区大小
// 无缓冲(同步):
ch1 := make(chan int) // 发送和接收必须同时准备好// 有缓冲(异步):
ch2 := make(chan int, 100) // 可以缓冲100个元素

http://www.xdnf.cn/news/1361737.html

相关文章:

  • 用 fastmcp 2.0 做一个“短期记忆(Redis)”的 MCP 服务器(Server)+ 一个简单的 Client 例子
  • Java项目-苍穹外卖_Day2
  • Ubuntu24.04配置yolov5
  • 使用 Gemini CLI作为 Claude Code的 subagent
  • 分布式锁设计实战:多级缓存防御设计优化同步性能
  • 《眼科学》10月版面征稿论文速递
  • Nestjs生命周期中全局方法执行顺序
  • 嵌入式开发学习———Linux环境下网络编程学习(六)
  • MySQL 行转列与列转行的实现方式
  • 在新塘SDK下面,有四中文件夹,GCC、IAR、KEIL、和Keil_AC6.这4个工程有什么区别。各自是怎样配置寄存器并实现SPI功能的
  • Aligning Effective Tokens with Video Anomaly in Large Language Models
  • Node.js面试题及详细答案120题(43-55) -- 性能优化与内存管理篇
  • 《飞算Java开发实战:从入门安装到项目部署》
  • 【GEE+Python 实战】用 Sentinel-2 监测 2024 年研究区 NDVI 变化(附完整源码与避坑指南)
  • Codejock Suite ProActiveX COM Crack
  • 一文掌握 Java 键盘输入:从入门到高阶(含完整示例与避坑指南)
  • LIANA | part1 intro部分
  • VMware Workstation 不可恢复错误:(vcpu-0)
  • 详细的周任务清单(Week1-Week24,每周具体目标+任务)
  • Socket some functions
  • 基于PHP服装租赁管理系统/基于php的服装管理系统的设计与实现
  • C#_gRPC
  • 【图像处理基石】基于 Python 的图像行人删除技术:实现街景无干扰化处理
  • 6.1Element UI布局容器
  • leetcode 162 寻找峰值
  • Polkadot - JAM
  • 13种常见机器学习算法总结
  • 青少年软件编程(python六级)等级考试试卷-客观题(2023年3月)
  • 学习制作记录(选项UI以及存档系统)8.24
  • 基于RISC-V架构的国产MCU在eVTOL领域的应用研究与挑战分析