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

【Go语言圣经2.4】

目标

理解

  1. 在 Go 中,赋值操作既包括最基本的形式(左边一个变量,右边一个表达式),也包括复合赋值、元组赋值和隐式赋值。
  2. 表达式求值的顺序、变量更新时的副作用以及如何处理多返回值和下划线(_)丢弃不需要的值

概念

  1. 可赋值性

    赋值语句要求左侧变量和右侧表达式的最终值必须有相同的数据类型:

    • 严格的类型匹配

      只有当右侧的值对于左侧变量是可赋值的,赋值才是允许的。如果类型不匹配,编译器会报错。

    • 特殊情况:nil 与常量

      • nil 可以赋值给任何指针或引用类型的变量。
      • 常量赋值有更灵活的规则,允许在一定条件下进行隐式转换,以避免额外的类型转换操作。
    • 与相等比较的关系

      对于使用 ==!= 进行比较时,只有当右侧的值对于左侧变量可赋值时,相等比较才有意义。

  2. 表达式求值顺序:

    • 在元组赋值中,右侧所有表达式会先求值,然后再一次性将结果赋给左侧的各个变量。这保证了在交换变量值或多个变量依赖的情况下不会出现意外的中间状态。
  3. 变量的概念与内存模型:每个变量在内存中都有固定位置,赋值语句实际上更新该位置中的数据。

要点

显式赋值

最基本的赋值形式是将一个表达式的值赋给一个变量或可寻址的表达式。例如:

  • 基本变量赋值

    x = 1
    

    将整数 1 赋给变量 x。

  • 指针赋值

    *p = true
    

    通过指针 p 间接将布尔值 true 赋给 p 指向的变量。

  • 结构体字段赋值

    person.name = "bob"
    
  • 数组、slice 或 map 元素赋值

    count[x] = count[x] * scale
    
  1. 复合赋值运算符

    对于某些二元算术运算和赋值的组合操作,Go 提供了简洁的写法

    count[x] *= scale
    

    这种复合赋值可以减少对变量表达式的重复计算,使代码更简洁。

自增与自减

v := 1
v++    // 等价于 v = v + 1,v 变为 2
v--    // 等价于 v = v - 1,v 变为 1
  • 自增和自减是语句而非表达式,不能像其它语言那样嵌入表达式中。
    • 不能将自增、自减操作用于赋值表达式中,如不能写成 x = i++

元组赋值(多重赋值)

元组赋值允许同时更新多个变量的值,且在更新前右边所有表达式都先计算好,再统一更新左边对应的变量。这对于解决一些变量相互依赖的问题非常有用:

  • 交换两个变量

    
    x, y = y, x
    

    同时交换 x 与 y 的值,而不需要临时变量。

  • 交换数组或 slice 中的元素

    
    a[i], a[j] = a[j], a[i]
    
  • 实际应用:计算最大公约数(GCD)

    
    func gcd(x, y int) int {for y != 0 {x, y = y, x%y}return x
    }

    每次循环中先计算 x%y,再将旧的 y 和 x%y 分别赋值给 x 和 y,实现算法逻辑。

  • 计算斐波那契数

    
    func fib(n int) int {x, y := 0, 1for i := 0; i < n; i++ {x, y = y, x+y}return x
    }

    每次迭代更新 x 和 y,用于生成斐波那契数列。

  • 元组赋值在 for 循环中也可使用

    
    i, j, k = 2, 3, 5

    注意:当赋值表达式较复杂时,过度使用元组赋值可能影响代码的可读性,简单情况优先考虑单个赋值。

处理多个返回值

在 Go 中,很多函数会返回多个值,例如错误处理常见于函数调用。元组赋值允许将这些值同时赋给多个变量:

  • 函数返回两个值

    
    f, err = os.Open("foo.txt")
    

    要求左侧的变量数量与函数返回值数量匹配。

  • map 查找、类型断言、通道接收

    这些操作有时会产生两个结果:

    
    v, ok = m[key]     // map 查找,ok 表示是否找到对应的键
    v, ok = x.(T)      // 类型断言,ok 表示断言是否成功
    v, ok = <-ch       // 通道接收,ok 表示接收是否成功(通道关闭时返回零值和 false)
    

    但它们也可以只产生一个结果:

    
    v = m[key]         // 查找失败时返回零值
    v = x.(T)          // 类型断言失败时会触发 panic
    v = <-ch           // 如果通道阻塞,则等待(不算失败)
    
  • 使用空白标识符丢弃不需要的值

    如果不需要某个返回值,可以使用下划线 _ 来丢弃:

    
    _, err = io.Copy(dst, src) // 丢弃字节数
    _, ok = x.(T) // 只检测类型,忽略具体值
    

隐式赋值行为

赋值不仅仅通过显式的赋值语句实现,很多场景中会隐式地发生赋值:

  • 函数调用

    调用函数时,调用参数的值会隐式地赋给函数的参数变量。

  • 返回语句

    返回值会隐式赋值给结果变量。

  • 复合类型字面量

    创建数组、slice、map 或结构体时,字面量初始化会隐式对每个元素或字段进行赋值。例如:

    medals := []string{"gold", "silver", "bronze"}
    

    相当于

    medals[0] = "gold"
    medals[1] = "silver"
    medals[2] = "bronze"
    

语言特性

  1. 在有命名返回值的函数中,当执行返回语句时,返回值会自动赋值给这些命名的返回变量,不需要在返回语句中单独写出它们。因为在函数体内,这些结果变量已经赋得了值。

    在 Go 语言中,函数可以定义命名返回值,也就是在函数签名中为返回值起一个名字。这样做的效果是,这些命名的返回值在函数体内就像局部变量一样存在。当执行 return 语句时,如果没有显式指定返回值,那么当前这些变量的值就会自动(隐式地)作为函数的返回值。

    例如,考虑下面的例子:

    
    func add(a, b int) (sum int) {sum = a + b // 这里把 a+b 的结果赋给了命名返回变量 sumreturn      // 隐式返回 sum,即返回 a+b 的结果
    }
    

    在这个函数中,我们声明了返回值变量 sum。在函数体内,我们将 a+b 的值赋给 sum,然后直接使用 return 语句返回。这里的 return 没有跟随任何值,但 Go 会自动把 sum 的当前值作为函数的返回值返回给调用者。

    这种方式的好处是:

    • 简洁:在函数的最后可以直接写 return,不必重复写返回变量。
    • 可读性:当返回值具有名称时,函数的返回含义更加明确。

    需要注意的是,如果在函数中使用了命名返回值,那么在函数结束时,无论是通过 return 语句还是到达函数末尾,Go 都会使用这些命名返回值的当前值作为最终的返回结果。这就是所谓“返回值会隐式赋值给结果变量”的含义。

总结

相关文章:

【Go语言圣经2.4】

目标 理解 在 Go 中&#xff0c;赋值操作既包括最基本的形式&#xff08;左边一个变量&#xff0c;右边一个表达式&#xff09;&#xff0c;也包括复合赋值、元组赋值和隐式赋值。表达式求值的顺序、变量更新时的副作用以及如何处理多返回值和下划线&#xff08;_&#xff09…...

运维工具推荐 -- 宝塔面板:一键部署服务器

标题&#xff1a;宝塔面板&#xff1a;一键部署服务器&#xff0c;轻松管理你的云端世界 引言 在数字化时代&#xff0c;服务器管理对于个人开发者、中小企业或站长来说既是机遇也是挑战。手动配置服务器环境耗时费力&#xff0c;而 宝塔面板 作为一款 免费开源、功能全面 的服…...

C# 异常处理‌的核心概念

文章目录 一、异常处理的核心概念‌‌二、C# 异常处理的基本语法‌‌三、常见异常类型‌‌四、最佳实践‌‌五、示例&#xff1a;文件读取异常处理‌‌六、总结‌ C# 异常处理‌的详细说明&#xff0c;包括核心概念、使用方法和最佳实践&#xff1a; 一、异常处理的核心概念‌ …...

腾讯云点播key防盗链生成到期自动失效url

package com.xmkjsoft.protect_key;import java.nio.charset.StandardCharsets; import java.security.MessageDigest;public class TencentKeyAntiTheft {private static final String SECRET_KEY ""; // 请替换为腾讯云 VOD 控制台中的 Key/*** 生成腾讯云 Key 防…...

深入 Spring Boot 注解

深入 Spring Boot 注解&#xff1a;我的开发心得与常用注解详解 大家好&#xff0c;我是 [你的 CSDN 昵称/名字]&#xff0c;一位热爱 Spring Boot 的技术博主。 在多年的 Spring Boot 开发实践中&#xff0c;我深深体会到注解的强大魅力。它们不仅让代码变得更简洁&#xff0…...

k8s环境部署

四台机器 分别是 k8s-master&#xff1a;172.25.254.100 k8s-node1&#xff1a;172.25.254.10 k8s-node2&#xff1a;172.25.254.20 docker-harbor&#xff1a;172.25.254.200 reg.timinglee.org 四台机器分别配置好网络和软件仓库 做好地址解析 scp -r /etc/hosts/ root17…...

CentOS 系统安装 docker 以及常用插件

博主用的的是WindTerm软件链接的服务器&#xff0c;因为好用 1.链接上服务器登入后&#xff0c;在/root/目录下 2.执行以下命令安装docker sudo yum install -y yum-utilssudo yum-config-manager \--add-repo \https://download.docker.com/linux/centos/docker-ce.reposudo…...

谷歌云服务器:服务器怎么安装???

谷歌云服务器&#xff1a;服务器怎么安装&#xff1f;&#xff1f;&#xff1f; 以下是详细分步指南&#xff0c;帮助你在 Google Cloud Platform (GCP) 上快速创建并配置云服务器&#xff08;Compute Engine 实例&#xff09;&#xff0c;并安装所需环境&#xff1a; 一、准备…...

Redis--Zset类型

目录 一、引言 二、介绍 三、命令 1.zadd 2.zrange&#xff0c;zrevrange&#xff0c;zrangebyscore 3.zcard&#xff0c;zcount 4.zpopmax&#xff0c;bzpopmax&#xff0c;zpopmin&#xff0c;bzpopmin 5.zrank,zrevrank,zscore 6.zrem&#xff0c;zremrangebyrank&a…...

《阿里云Data+AI:开启数据智能新时代》电子书上线啦!

本书整理了阿里云在DataAI领域的最新实践案例与深度洞察&#xff0c;涵盖电商、游戏、营销、数字内容等多个行业的成功经验&#xff0c;以及技术专家对数据库与AI融合趋势的专业解读。 通过理论与实践的结合&#xff0c;我们将共同探索DataAI如何成为企业智能化转型的核心驱动…...

图像处理篇---图像预处理

文章目录 前言一、通用目的1.1 数据标准化目的实现 1.2 噪声抑制目的实现高斯滤波中值滤波双边滤波 1.3 尺寸统一化目的实现 1.4 数据增强目的实现 1.5 特征增强目的实现&#xff1a;边缘检测直方图均衡化锐化 二、分领域预处理2.1 传统机器学习&#xff08;如SVM、随机森林&am…...

Vue 3 事件总线详解:构建组件间高效通信的桥梁

Vue 3 事件总线详解&#xff1a;构建组件间高效通信的桥梁 为什么需要事件总线&#xff1f;使用 mitt 实现事件总线1. 安装 mitt2. 创建事件总线3. 在组件中使用事件总线发送端组件&#xff08;例如 ComponentA.vue&#xff09;接收端组件&#xff08;例如 ComponentB.vue&…...

Golang编译器DIY,手搓 if err != nil { return err } 语法糖

前序 在go的社区里&#xff0c;下面这三行代码是被吐槽的最多的 if err ! nil {return err }从代码之整洁美观的角度看&#xff0c;这样的写法也是让人不舒服的。尤其是 当有很多错误需要处理的时候&#xff0c;就会发现通篇都是这三行。 所以想着看看修改一下编译器&#xf…...

图解多头注意力机制:维度变化一镜到底

目录 一、多头注意力机制概述二、代码实现1. pyTorch 实现2. tensorFlow实现 三、维度变化全流程详解1. 参数设定2. 维度变化流程图3. 关键步骤维度变化 四、关键实现细节解析1. 多头拆分与合并2. 注意力分数计算3. 掩码处理技巧 五、完整运行示例六、总结与常见问题1. 核心优势…...

.NET_Prism基本项目创建

Prism简述 模块&#xff08;Module&#xff09;&#xff1a;独立的功能单元&#xff0c;可动态加载。依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;&#xff1a;通过 IoC 容器&#xff08;如 Unity、Autofac&#xff09;管理模块之间的依赖关系。&#…...

BigEvent项目后端学习笔记(一)用户管理模块 | 注册登录与用户信息全流程解析(含优化)

&#x1f4d6; 模块概述 用户管理模块是系统的核心基础模块&#xff0c;包含 注册、登录、用户信息维护 等功能。本模块涉及 JWT Token认证、密码加密存储、文件上传 等关键技术点&#xff0c;是理解前后端分离架构中安全与数据交互的典型实践。本篇对于原项目进行了代码优化&…...

[ISP] 人眼中的颜色

相机是如何记录颜色的&#xff0c;又是如何被显示器还原的&#xff1f; 相机通过记录RGB数值然后显示器显示RGB数值来实现颜色的记录和呈现。道理是这么个道理&#xff0c;但实际上各厂家生产的相机对光的响应各不相同&#xff0c;并且不同厂家显示器对三原色的显示也天差地别&…...

解锁MySQL 8.0.41源码调试:Mac 11.6+CLion 2024.3.4实战指南

文章目录 解锁MySQL 8.0.41源码调试&#xff1a;Mac 11.6CLion 2024.3.4实战指南前期准备环境搭建详细步骤安装 CLion安装 CMake 3.30.5准备 MySQL 8.0.41 源码配置 CMake 选项构建 MySQL 项目 调试环境配置与验证配置 LLDB 调试器启动调试验证调试环境 总结与拓展 解锁MySQL 8…...

celery入门

按照Celery 官方文档&#xff0c;用 Django Celery Redis 写的一个简单项目 如需转载&#xff0c;标记出处 环境准备 1. 安装依赖 pip install django celery redis 创建 Django 项目 1. 创建 Django 项目和 APP django-admin startproject myproject cd myproject python …...

关于xcode Project navigator/项目导航栏的一些说明

本文基于 xcode12.4 版本做说明 首先要明确一点&#xff0c;导航栏这里展示的并不是当前工程在电脑硬盘中的文件结构&#xff0c;它展示的是xxxxxx.xcodeproj/project.pbxproj文件(后文简.pbxproj文件)中的内容。我们在导航栏中的操作就是修改该文件&#xff0c;有些操作会修…...

深度解析扣减系统设计:从架构到实践

背景 在当今数字化业务蓬勃发展的时代&#xff0c;扣减系统在众多业务场景中扮演着关键角色。无论是电商平台的库存扣减&#xff0c;还是金融领域的资金扣减、积分系统的积分扣减&#xff0c;一个高效、可靠且数据一致的扣减系统都是业务稳健运行的基石。本文将深入探讨扣减系…...

视觉定位项目中可以任意修改拍照点位吗?

修改拍照点位不是那么简单 1. 背景2. 修改拍照点位意味着什么&#xff1f;3. 如何解决这个问题&#xff1f; 1. 背景 在视觉定位的项目中&#xff0c;会遇到这么一种情况&#xff1a;完成三步&#xff08;9点标定&#xff0c;旋转中心标定&#xff0c;示教基准&#xff09;之…...

深度学习常用操作笔记

深度学习常用操作笔记 指令报错cannot import name Config from mmcvImportError: cannot import name print_log from mmcvImportError: cannot import name init_dist from mmengine.runnerWARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNon…...

C++学习内存管理

1.概念的介绍 总括&#xff1a; 1. 栈&#xff08;Stack&#xff09; 存储内容&#xff1a; 局部变量&#xff08;包括函数参数、非静态局部变量&#xff09;。 函数调用的上下文信息&#xff08;如返回地址、寄存器状态等&#xff09;。 特点&#xff1a; 内存由编译器自动…...

git使用。创建仓库,拉取分支,新建分支开发

文章目录 安装 git自己新建仓库&#xff0c;进行代码管理合作开发的流程拉去主分支代码查看本地分支的状态查看远程分支查看远程的仓库信息本地分支切换切换并创建分支提交代码 made by NJITZX git 是一个版本控制工具&#xff0c;真正开发项目中是多个人开发一个项目的&#…...

itsdangerous加解密源码分析|BUG汇总

这是我这两天的思考 早知道密码学的课就不旷那么多了 纯个人见解 如需转载&#xff0c;标记出处 目录 一、官网介绍 二、事例代码 源码分析&#xff1a; 加密函数dump源码使用的函数如下&#xff1a; 解密 ​编辑 ​编辑 关于签名&#xff1a; 为什么这个数字签名没有…...

常见限流算法及实现

1. 固定窗口计数器&#xff08;Fixed Window Counter&#xff09; 原理&#xff1a;在固定时间窗口&#xff08;如1分钟&#xff09;内统计请求数&#xff0c;超过阈值则拒绝后续请求。优点&#xff1a;实现简单&#xff0c;内存占用低。缺点&#xff1a;存在窗口切换时的流量…...

计算机操作系统进程(4)

系列文章目录 第二章&#xff1a;进程的描述与控制 文章目录 系列文章目录前言一、临界区的概念和描述&#xff1a;二、硬件同步机制&#xff1a; 1.关中断2.利用Test-and-Set指令实现互斥3.利用Swap指令实现进程的互斥 总结 前言 上一篇我们仅仅讲了一点关于线程同步的概念&a…...

编程题《牛牛的链表删除》的python可以用非链表的方式

描述 牛牛从键盘输入了一个长度为 n 的数组&#xff0c;把这个数组转换成链表然后把链表中所有值是 x 的节点都删除。 输入描述&#xff1a; 第一行输入两个正整数 n 和 x 表示数组的长度和要删除的链表节点值 x 。 第二行输入 n 个正整数表示数组中每个元素的值。 输出描述&am…...

Certbot实现SSL免费证书自动续签(CentOS 7版 + Docker部署的nginx)

前置安装&#xff0c;可参考Certbot实现SSL免费证书自动续签&#xff08;CentOS 7 nginx/apache&#xff09; 如果是通过 Docker 运行 Nginx&#xff0c; certbot 无法直接检测到本地的 Nginx 配置。解决方案是 使用 standalone 模式 或 挂载 Webroot 方式获取 SSL 证书&…...