【Go语言圣经2.3】

【Go语言圣经】从零开始学Go----1.入门篇 《Go语言圣经》读书笔记,完整知识点整理,从零开始学Golang 阅读详情

目标

了解Go 的变量声明有以下几个重要特点:

  • 声明方式多样
    • 使用 var 关键字可以显式声明变量、指定类型或初始化值。
    • 使用简短声明符号 := 可以在函数内部快速声明并初始化变量,类型由编译器自动推导。
  • 零值初始化
    • 如果在声明时没有提供初始化表达式,变量会被赋予类型对应的“零值”:数值为 0,布尔为 false,字符串为空字符串,指针、slice、map、chan、函数等为 nil。
  • 多变量声明与多重赋值
    • 同一个声明语句中可以同时声明多个变量,甚至允许类型各不相同(通过初始化表达式推导)。
    • 还可以利用函数返回值进行多变量的声明和初始化。
  • 变量与指针
    • 每个变量对应一块内存区域,指针变量存储其他变量的地址,通过指针可以间接读取或修改目标变量的值。
  • 变量的生命周期与作用域
    • 包级变量在整个程序运行期间存在,而局部变量仅在所在函数(或块)内有效。
    • 编译器通过“逃逸分析”决定局部变量是分配在栈上还是堆上,从而影响性能和内存回收。

概念

  1. 零值

    • 之所以需要零值初始化:每个变量声明后都有一个“合理”的初始状态,避免出现未初始化的情况,从而减少潜在的错误
    • 各类型的零值:
      • 数值类型:0
      • 布尔类型:false
      • 字符串:“”
      • 指针、slice、map、chan、函数、接口:nil
      • 数组、结构体等聚合类型:每个元素或字段都被初始化为对应类型的零值
  2. 内存管理

    • 变量和内存:

      每个变量在内存中都有一个地址。变量声明时分配内存空间,指针保存该内存地址,可以直接操作内存中的数据。

    • 栈与堆:

      • 栈:用于分配局部变量,速度快但空间有限(因此分配和回收速度快)
      • 堆:当变量需要在函数外部保持有效时,可能会分配在堆上,由垃圾回收器管理。
  3. 变量的生命周期与作用域

    变量的生命周期决定了它们在内存中存在的时间长短,而作用域决定了变量在代码中可以被访问的范围。

    • 包级变量:
      • 在包级(文件最外层)声明的变量,其生命周期与整个程序运行周期相同。
      • 可以在同一包的所有文件中访问(如果名字符合可见性规则)。
    • 局部变量:
      • 在函数或代码块中声明的变量,其生命周期仅限于所在的作用域。
      • 当变量不再被引用时,自动成为垃圾回收的对象。
    • 逃逸分析:
      • 如果局部变量的地址被引用到外部(例如赋值给包级变量),则称该变量“逃逸”到堆上,其生命周期会延长。
      • 编译器会自动决定局部变量分配在栈上还是堆上,但逃逸变量可能会影响性能,因为堆分配和垃圾回收开销较大。
    • 垃圾回收:Go 的垃圾收集器通过从全局变量和当前活动函数的局部变量出发,跟踪所有可达变量来决定哪些变量可以回收。只要变量不再被引用,它们的内存就会被自动释放。
      • 从每个包级的变量和每个当前运行函数的每一个局部变量开始,通过指针或引用的访问路径遍历,是否可以找到该变量。如果不存在这样的访问路径,那么说明该变量是不可达的,也就是说它是否存在并不会影响程序后续的计算结果。
      • 因为一个变量的有效周期只取决于是否可达,因此一个循环迭代内部的局部变量的生命周期可能超出其局部作用域。同时,局部变量可能在函数返回之后依然存在。

要点

基本的var声明

var 变量名字 类型 = 表达式
  • 类型或表达式可省略
    • 如果省略类型,则根据初始化表达式推导类型;
    • 如果省略初始化表达式,则使用该类型的零值来初始化变量。

同时声明多个变量

var i, j, k int                 // 三个变量都是 int 类型
var b, f, s = true, 2.3, "four" // 类型分别为 bool、float64、string,由初始化表达式推导

  1. 多变量声明的灵活性:可以在一条声明语句中声明多个变量,即使它们类型不相同(前提是给出初始化表达式)。

    var f, err = os.Open(name) // os.Open 返回一个文件和一个错误信息
    
    

    利用函数返回值声明变量:这种方式非常适用于需要同时获取多个返回值的情况。

简短变量声明(:=)

  1. 在函数内部,Go 提供了更简洁的变量声明方式:

    i := 100
    anim := gif.GIF{LoopCount: nframes}
    
    
    • 自动推导变量类型,不需要显式指定;
    • 只能用于局部变量声明,不能在包级使用;
    • 注意“:=”不仅声明变量,还会同时进行初始化。
    i, j := 0, 1
    
    
  2. 与赋值操作的区别:

    • “:=”用于声明并初始化,至少有一个变量是新声明的;
    • “=” 则纯粹是赋值,不引入新的变量;

    例如,下面的代码会编译错误,因为没有新的变量被声明

    f, err := os.Open(infile)
    // ...
    f, err := os.Create(outfile) // 错误:没有新变量
    
    
  3. 变量混合声明:

    如果同一词法域中已有部分变量存在,那么“:=”会对已有变量进行赋值,同时声明新的变量

    in, err := os.Open(infile) // 声明 in 和 err
    // ...
    out, err := os.Create(outfile) // 如果 err 已经存在,则只新声明 out,且对 err 进行赋值
    
    

指针

指针是变量存储地址的引用,允许直接操作内存中的数据。

  1. 使用 & 运算符获取变量的地址

    x := 1
    p := &x // p 的类型为 *int,存储 x 的内存地址
    
  2. 访问指针指向的值:
    使用 * 运算符来读取或修改指针指向的值

    fmt.Println(*p) // 读取 p 指向的 x 的值,即 1
    *p = 2          // 修改 p 指向的 x 的值为 2
    
    
  3. 指针零值:所有类型的指针零值为 nil ,这表示指针没有指向任何有效的内存地址。

  4. 指针比较:可以比较指针是否相等,只有当它们指向同一个变量或都为 nil 时,结果为 true。

    var x, y int
    fmt.Println(&x == &x, &x == &y, &x == nil) // 输出: true false false
    
    
  5. 指针创建别名

    对同一变量取地址或复制指针,都为该变量创建了新的别名,通过 *p 访问到的就是同一个变量的值

  6. 函数中返回局部变量地址:在 Go 中,返回函数中局部变量的地址是安全的,因为编译器会根据逃逸分析决定将该变量分配在堆上。例如:

    func f() *int {
        v := 1
        return &v
    }
    fmt.Println(f() == f()) // 输出 false,每次调用返回的地址不同
    
    
  7. 通过传递指针作为参数,可以在函数内部直接更新变量的值

    func incr(p *int) int {
        *p++      // 增加 p 指向的变量的值,但不改变 p 本身
        return *p
    }
    v := 1
    incr(&v)      // v 变为 2
    fmt.Println(incr(&v)) // 输出 3,同时 v 为 3
    
    

new 函数

  1. 除了使用 var 声明变量外,Go 还提供了内建函数 new 来创建变量。

    p := new(int)
    fmt.Println(*p) // 输出 0(int 的零值)
    *p = 2
    fmt.Println(*p) // 输出 2
    
    
    • new(T) 会创建一个 T 类型的匿名变量,将其初始化为 T 的零值,并返回其地址(类型为 *T)。

      • 它相当于一种语法糖,可以在表达式中使用,而不需要显式声明变量名。
    • 每次调用 new 都会返回一个新的变量地址,因此两个 new 的结果通常不同

      p := new(int)
      q := new(int)
      fmt.Println(p == q) // 输出 false
      
      
  2. 注意事项

    • new 不是关键字,可以被重新定义,这时在当前作用域内将无法使用内置 new 函数;
    • 对于结构体和其他复杂类型,通常推荐使用字面量语法(例如:&T{...})来创建变量,因为更灵活。

逃逸

var global *int

func f() {
    var x int
    x = 1
    global = &x  // x 的地址赋给全局变量,因此 x 必须在堆上分配
}

func g() {
    y := new(int)
    *y = 1       // y 是局部变量,但如果不逃逸,编译器可能将其分配在栈上
}

语法特性

  1. 多重赋值:Go 允许一次对多个变量赋值,常用于交换变量值或同时处理多个返回值。这是 Go 语言简洁语法的重要组成部分。
深入AutoSar诊断协议栈:当ECU报故障时,FiM模块是如何悄悄“阉割”功能的? 本文深入解析AutoSar诊断协议栈中FiM模块的工作原理,揭示ECU报故障时如何通过Inhibition Counter和位运算技术实现功能静默降级。探讨FiM在故障处理链中的关键角色,包括功能权限仲裁、降级策略执行和系统安全兜底,并分享实战调试技巧与进阶应用案例。 阅读详情

相关推荐

保姆级教程:从AD导出Gerber到HFSS 3D Layout导入,搞定PCB电磁仿真全流程

本文提供从Altium Designer导出Gerber文件到Ansys HFSS 3D Layout导入的完整PCB电磁仿真流程指南。详细讲解Gerber文件导出设置、HFSS中的3D模型重建技巧,以及电磁仿真中的常见问题解决方案,帮助工程师高效完成高速电路和射频设计的性能验证。

weixin_30379531的博客 705

Go语言圣经

第一章入门

kwdecsdn的博客 2754

[终于解决]Ubuntu14.04 32位安装移动网卡(0bda:b711)驱动8188gu tplink-WN726n

大致梳理一下问题解决的流程 首先,在台式机做了双系统,台式机只有一个网线接口,由于项目要求,需要占用网口传输数据,所以用之前买的tplink-WN726n免驱版2.0的移动网卡 【note】免驱版只能在Windows下安装使用,在Ubuntu系统中无法使用,所以,需要另辟蹊径。 找了很多资料,尝试很多方法,有的复杂有的简单,终于解决。 【思路】首先在Ubuntu系统中输入lsusb,查看是否检测到USB网卡设备。然后从Github中复制代码,构建,安装,然后modprobe一下,到前面那步还不行,就再来一步

瑞o 1万+

Go语言圣经总结

如果没有足够的增长空间的话,appendInt函数则会先分配一个足够大(2*len(old_slice),这个扩容算法因不同语言不同)的slice用于保存新的结果,先将输入的x复制到新的空间,然后添加y元素。当调用一个函数的时候,函数的每个调用参数将会被赋值给函数内部的参数变量,所以函数参数变量接收的是一个复制的副本,并不是原始调用的变量。因为函数参数传递的机制导致传递大的数组类型将是低效的,并且对数组参数的任何的修改都是发生在复制的数组上,并不能直接修改调用时原始的数组变量。

yelvens的博客 2058

MediaPipeUnityPlugin(最新版)摇摆拳人脸识别

MediaPipeUnityPlugin(最新版)摇摆拳人脸识别

不忘初心 方得始终 2978

多径衰落信道的 MATLAB 仿真

在无线通信系统中,信号在传输过程中会经历多径传播现象,导致信号在接收端出现时域和频域上的扩展。通过以上示例代码,我们可以进行多径衰落信道的 MATLAB 仿真。同时,我们还可以通过调整信道参数和信号特性,进一步研究多径衰落对系统性能的影响。常用的模型之一是瑞利衰落信道模型,它假设信号在传输过程中受到多个散射路径的影响。除了瑞利衰落信道模型,我们还可以使用其他类型的信道模型,如高斯衰落信道模型。在上述代码中,我们首先定义了信道的参数,包括最大多普勒频移、多径延迟和多径功率衰落。函数来模拟高斯衰落信道。

TechCraze的博客 665

Go语言圣经(中文版)

http://golang-china.github.io/gopl-zh/index.html

dazheng 1万+

【DRAM存储器六十六】DDR5介绍--训练相关之CA/CS Training

详述DDR5 CA/CS training过程细节

highman110的博客 195

GO语言从入门到达人--GO语言圣经--入门

1.Go的一些基本规范 GO是编译型语言。Go的工具链讲程序的源文件转变为机器相关的原生二进制 GO原生地支持Unicode,支持任何国家的语言。 GO语言其实由三部分组成 : 1.声明自己属于哪个包 package main 2.导入其他包 import (“fmt”) 3.程序本身 func main(){ 代码块 } 一般import后面是组成函数 – func 函数 const 常量 var 变量 type 类型 GO语言不适用分号进行结尾。 GO语言的" { "是不可以单独一行的,必须与f

weixin_44324366的博客 670

OpenCASCADE:Direct3D CSharp 示例

OpenCASCADE:Direct3D CSharp 示例OpenCASCADE:Direct3D CSharp 示例 OpenCASCADE:Direct3D CSharp 示例 此示例演示了如何在使用CSharp和Windows Presentation Foundation (WPF)编写的.Net应用程序中使用 OCCT 和 DirectX 库。 .Net、OCCT (C++) 和 DirectX 级别之间的连接由用 C++/CLI 编写的代理库OCCProxy和D3DProxy提供。代理库OCC

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1824

FPGA实现AXI-Stream通信

本文介绍了在FPGA中实现AXI-Stream接口的工业级方案,重点解析了核心协议信号(TVALID/TREADY/TDATA/TLAST)与可选扩展信号,并提供了Verilog最小化实现示例。文章详细阐述了握手协议规则、时序约束方法,以及吞吐量优化技巧(如寄存器切片和双缓冲策略),同时给出了跨时钟域处理的异步FIFO解决方案。此外,还包含验证调试方法(Testbench结构和ILA触发设置)和典型应用场景(视频处理/网络传输),最后提供了资源消耗参考数据。该实现方案严格遵循Xilinx/Intel官方规范

whm128的博客 1463

go语言复数包_Go语言圣经 2.3-复数

Go提供了两种大小的复数类型:complex64和complex128,分别由float32和float64组成。内置函数complex从指定的实部和虚部构建复数,内置函数real和imag用来获取复数的实部和虚部:var x complex128 = complex(1, 2) // 1+2ivar y complex128 = complex(3, 4) // 3+4ifmt.Println(...

weixin_39598472的博客 179

一台NAS两个系统:飞牛nas上完美运行群晖DSM?(飞牛nas+群晖nas套娃安装实操)

想在飞牛NAS上体验群晖DSM系统?💡 本文详细记录了飞牛nas上部署群晖的完整过程,从镜像转换到系统安装,每一步都有详细说明 🖥️,让你在不增加硬件成本的情况下,轻松实现一套硬件、多种系统的灵活部署 ✅

XiaoqiangClub的博客 2366

【go语言圣经】练习2.3-2.5

表达式 x&(x-1) 用于将x的最低的一个非零的bit位清零。使用这个算法重写PopCount函数,然后比较性能。(PS:每次运算x&(x-1)可以将x二进制形式中排在最后的那一位1给消除,只需要计算消除1的次数即可)用移位算法重写PopCount函数,每次测试最右边的1bit,然后统计总数。重写PopCount函数,用一个循环代替单一的表达式。比较两个版本的性能。在做题前,首先解析一下本章节中的popcount.go文件中的代码。查表算法的性能差异。

yj1248805281的博客 383

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Go 语言圣经 9.2 sync.Mutex互斥锁 9.3 sync.RWMutex读写锁

9.2 sync.Mutex互斥锁 知识点 1.一个只能为1和0的信号量叫做二元信号量(binary semaphore) 2.这种互斥很实用,而且被sync包里的Mutex类型直接支持 3.Lock和Unlock的调用是在所有路径中都严格配对的 4.一个deferred Unlock即使在临界区发生panic时依然会执行 5.defer调用只会比显式地调用Unlock成本高那么一点...

Anglemiku_v 464

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

《GO语言圣经》学习初感与建议

前言 今天刚看了《GO语言圣经》的前二十页,感触颇深,深感此书之精髓,令人叹服,决定从今日起,记录下啃书的收获与感悟,与君共勉!!! 在记录中,我会有选择的进行分享,对那些自我感觉比较关键的细细解读,一些不是太重要的我就简单略过了,以此节省大家的时间。有兴趣的小伙伴可以边看书边看我的博客,有什么想法跟我交流交流,一起进步一起成长,效果想必是极好的。 学习建议 首先说一下,我自学GO...

weixin_42940826的博客 6936

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

[日常] Go语言圣经--并发的循环习题

练习 8.4:修改reverb2服务器,在每一个连接中使用sync.WaitGroup来计数活跃的echo goroutine。当计数减为零时,关闭TCP连接的写入,像练习8.3中一样。验证一下你的修改版netcat3客户端会一直等待所有的并发“喊叫”完成,即使是在标准输入流已经关闭的情况下。 重点:等待所有的goroutine执行完成后再关闭TCP连接 package main ...

weixin_34370347的博客 92

【Go语言圣经2.4】

理解可赋值性赋值语句要求左侧变量和右侧表达式的最终值必须有相同的数据类型:严格的类型匹配只有当右侧的值对于左侧变量是可赋值的,赋值才是允许的。如果类型不匹配,编译器会报错。特殊情况:nil 与常量与相等比较的关系对于使用 或 进行比较时,只有当右侧的值对于左侧变量可赋值时,相等比较才有意义。表达式求值顺序:变量的概念与内存模型:每个变量在内存中都有固定位置,赋值语句实际上更新该位置中的数据。最基本的赋值形式是将一个表达式的值赋给一个变量或可寻址的表达式。例如:基本变量赋值 将整数 1 赋给变量 x。指针

Pyroyster的博客 1034

【go语言圣经1.3】

标准化输出 format格式化动词%d 十进制整数%x, %o, %b 十六进制,八进制,二进制整数。%f, %g, %e 浮点数: 3.141593 3.141592653589793 3.141593e+00%t 布尔:true或false%c 字符(rune) (Unicode码点)%s 字符串%q 带双引号的字符串"abc"或带单引号的字符'c'%v 变量的自然形式(natural format)%T 变量的类型%% 字面上的百分号标志(无操作数)转义字符。

Pyroyster的博客 882

【Go语言圣经3.1】

你有一个数字钟表,比如钟表上标有数字0到11。当你往前走时,比如从10走2步,就会变成0。两的补码就利用了这种“绕圈”的特性,把数字“绕回来”来表示负数。“两的补码”这个名字来源于它表示负数的方法:在二进制中,用一种方法把一个正数变成它的负数,而这个方法实际上就是用“2的幂”来做补数。因为2^n的基础是2,所以这种方法叫做两的补码。假设我们用8位二进制来表示数字,负数的表示其实就是“2^8减去正数”。比如-5此时是256-5。

Pyroyster的博客 794

go语言圣经读书笔记(上)

总而言之,go总结了很多厉害语言经验,由大佬们组队创造的,如图。

weixin_56551472的博客 1971

《go 语言圣经》笔记

最近看了《go 语言圣经》这本书,发现 go 语言很有趣,对于语法就不必关注,主要记录了一些语言特性(相对于其他语言而言)的笔记。 Go(又称Golang)是 Google 开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。 package Go 语言的代码通过包(package)组织,包类似于其它语言里的库(libraries)或者模块 (modules)。 Go语言中的包和其他语言的库或模块的概念类似,目的都是为了支持模块化、封装、单独编译和代码重用。每个包都对应一个独立的名字

fcsfcsfcs的博客 795

【Go语言圣经3.6】

iota 常量生成器:iota 是一个强大的工具,可以方便地生成有规律的数值序列,适用于枚举、位标志、以及其他有序数值集合的定义。有一类常量称为“无类型常量”,这类常量在声明时不被赋予一个具体的基础类型,而是保持一种更“通用”的状态。这样做有两个好处:更高精度的运算:无类型常量在算术运算中拥有比具体类型(如 int 或 float64)更高的精度(可以看作有 256 位或更多位的精度)。灵活的隐式转换。

Pyroyster的博客 1199

Go学习圣经:0基础精通GO开发与高并发架构(1)

从Java高薪岗位和就业岗位来看,云原生、K8S、GO 现在对于 高级工程师/架构师来说,越来越重要。尼恩从架构师视角出发,基于自己的尼恩 3高架构师知识体系和知识宇宙,写一本《GO学习圣经》。

架构师尼恩 4753

【Go语言圣经】从零开始学Go----2.程序结构

《Go语言圣经》读书笔记,完整知识点整理,从零开始学Golang

2301_79819426的博客 1136

go语言圣经中文版pdf_我的 Go 语言学习之路

原创: Go中文网 Go语言中文网 个人情况简介徐新华(polaris),Go 中文网站长。目前在北京一家创业公司担任 CTO。2011 年春,北京大学硕士毕业,先后在开心网、奇虎 360 工作。本人一直从事服务端相关工作,有着丰富的经验,对前端也有所掌握,Android 开发也了解些。虽然目前管理方面的事情较多,但一直保持着技术学习。擅长服务端技术和架构。我与 Go 语言2012 年 3 月,G...

weixin_39890629的博客 1415
上一篇: 【Go语言圣经】2.2 声明
下一篇: 【Go语言圣经2.4】
Pyroyster
博客等级 码龄7年 206粉丝 55原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值