前言

上篇内容,介绍了如何在不同的系统上安装 Go 开发环境和部分参数的配置,也简单介绍了 package 的概念、导入方式和我对包的初始化过程的理解,关于初始化顺序的理解,可能有错误,后期会有修改,也希望大家能指出来,帮助我学习下,谢谢。

这篇内容,讲些基础的知识,比如变量的声明方式、变量的重声明和重命名区别。

变量的声明

Go 语言中,变量的声明有几种方式,如:

var i,j int = 1,2
var i,j = 1,"2"
i,j,k := 1,"2",true
var (
m int=4
n = "Golang"
r = true
)

这里面比较特殊的是 i,j,k := 1,"2",true ,这在 Go 语言里被称为短声明,它有一个特殊点,就是不能在包级作用域中使用,只能在函数或块中使用。这里涉及到我要讲的两个知识点,变量重声明重名变量

变量的重声明

什么是变量的重声明?让我们用个例子来解释吧:

var err error
n,err:=io.WriteString(os.Stdout,"Hello world!\n")

从代码中我们看到,err 在第一行被声明了,接着我们又使用短声明的方式重新给它了值,注意这里没有变量重名即变量覆盖,发生的是变量重声明,这些代码在一个代码块中,如果你不确定,可以输出下变量地址看看是否有改变。这里我们先注意下变量重声明的前提条件,如下:

  1. 由于变量的类型在初始化时就已经确定,所以再次声明时赋予的类型必须与原本的相同,否则编译报错。

  2. 变量的声明只能发生在同一个代码块中。如果是与不同的代码块的变量重名,那么就是变量重名了,下文会介绍。

  3. 变量的重声明只有在短变量声明时才会发生,否则便已报错。

  4. 被声明的变量必须有多个,而且其中至少有一个新变量,而且不能使用 _ 表示新变量。

上面提到了变量重名,如果你是个老鸟,那么你肯定知道,你可以略过这个例子了:

var name = "Tom"
{
name := []string{"Jerry"}
fmt.Printf("%v\n",name)
}
fmt.Printf("%s\n",name)

也许心细如你,发现了不同,没错这两次变量的声明发生在了不同的代码块,这次就是变量的覆盖了,好了现在我们可以总结下两者的区别了

  1. 变量的重声明必须在同一代码块中,注意是 同一代码
  2. 变量重声明是对同一变量的的多次声明,即变量只有一个。
  3. 变量重声明,不论多少次其类型始终一致,必须遵从它的次声明指定的类型。而重名变量则不存在类型一致的限制,可以是任意不同类型。
  4. 如果可重名变量所在代码存在直接或间接的嵌套关系v,那么肯定会存在“屏蔽”现象,而变量重声明不会。

数组和切片

数组(array)类型和切片(slice)类型,两者都属于集合类型,都是存储了某一类型的值,这么看貌似它们没有什么区别,先让我们通过几个简单的例子看下区别。

数组的长度在声明时就需要给定,以后对其的使用是不能改变其长度的,也就是说长度是类型的一部分。

比如[5]int与[6]int是不同的两种数组类型;然后切片的类型字面量中只有元素的类型,而没有其长度。换句话说,切片的长度可以随着其中的元素增长而增长,但不会随着减少而减少。让我们看下几个示例,如下:

// 一维数组
array1 :=[6]int
// 二维数组
array2 :=[10][20]string
// 这里还是数组,自动计算数组的长度
array3 :=[...]int{10,20,30,40}
// 切片,len()=cap()=1
slice1 :=[]int{1}
// 声明一个长度为5,但容量为10的string类型的切片,长度和容量都是可变。容量参数10可省略,那么该slice的容量跟长度一致都是5
slice3 := make([]string,5,10)
// 连续插入多个值,其实后面也是个slice
slice1=append(slice1,2,3,4)
// 从slice1第二个素开始取出两个并组成一个新的切片,slice1和slice2是共享一个底层数组的。len(slice2)=2,cap(slice2)=3
slice2:=slice1[1:3]
// 如果这里修改了slice2的第一个元素值,slice1会有变化么,想想,不确定的话可以自己尝试输出下
slice2[0]=-2
// 这里又声明了slice4,似乎与slice2有些区别,那么区别在哪呢?
slice4:=slice1[1:3:3]

看了上面的示例代码,也许对切片会有更多的疑惑,别急现在我们一一解答。

示例代码中 slice2:=slice1[1:3] 这里使用切片slice1创建了一个新切片,其长度 len(slice2)cap(slice2) 分别是2,3。为什么其容量是3呢?先解释下这个声明语句,slice1[1:3] 第一个值表示新切片开始的元素位置,这里是1,表示是从slice1的第二元素开始。第二个值表示开始的索引位置(1),加上希望包含的元素个数(2),1+2的结果就是3,所以第二个值就是3,但要注意这里是不包含第二个值代表的索引位置的值,这里是数学中前开后闭的区间。那么第二个切片的容量怎么计算的呢?由于两个切片共享同一个底层数组,底层数组的容量是4,由于slice2是从索引位置为(1)开始,那么slice2的容量就是4-1=3,所以容量就是3。由于这两个切片共享同一个底层数组,所以 slice2[0]=-2 语句是修改的底层数组的值,对应的slice1[1]位置的值也被修改。想一下下面的代码输出结果是什么?

slice1:=[]int{1,2,3,4}
slice2:=slice1[1:3]
slice2=append(slice2,5)
fmt.Printf("s1:%v\n",slice1)
fmt.Printf("s2:%v\n",slice2)

你想到的输出结果,跟下面一样么?

s1:[]{1,2,3,5}
s2:[]{2,3,5}

上面提到 slice2:=slice1[1:3] 中有第三个参数,新切片的容量,默认是可忽略的,此时新切片的容量是 cap(slice1)-1 。你也可以加入第三个参数,但你要记住它是不能超过底层数组的容量的,也不能小于第二个参数值否则编译报错,如 slice2:=slice1[1:3:3] ,此时新切片的容量变成了3-1=2,跟长度一致,但前提是cap(slice2)的容量不能超过底层数组的容量cap(slice1),也不能少于len(slice2)。想一下,第三个参数有什么作用呢?

Go学习笔记02的更多相关文章

  1. 软件测试之loadrunner学习笔记-02集合点

    loadrunner学习笔记-02集合点 集合点函数可以帮助我们生成有效可控的并发操作.虽然在Controller中多用户负载的Vuser是一起开始运行脚本的,但是由于计算机的串行处理机制,脚本的运行 ...

  2. 机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN)

    机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN) 关键字:邻近算法(kNN: k Nearest Neighbors).python.源 ...

  3. OpenCV 学习笔记 02 使用opencv处理图像

    1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...

  4. SaToken学习笔记-02

    SaToken学习笔记-02 如果排版有问题,请点击:传送门 常用的登录有关的方法 - StpUtil.logout() 作用为:当前会话注销登录 调用此方法,其实做了哪些操作呢,我们来一起看一下源码 ...

  5. Redis:学习笔记-02

    Redis:学习笔记-02 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 4. 事物 Redis 事务本 ...

  6. OGG学习笔记02

    实验环境:源端:192.168.1.30,Oracle 10.2.0.5 单实例目标端:192.168.1.31,Oracle 10.2.0.5 单实例 1.模拟源数据库业务持续运行 2.配置OGG前 ...

  7. 《Master Bitcoin》学习笔记02——比特币的交易模型

    比特币的交易模型 模型基本描述 前面一篇学习笔记01提到了一个交易模型(第三章的内容),在第五章中,除了对这个模型做个详细介绍之外,其实和我上一篇理解的交易模型差不多,一个交易包含输入与输出,比特币是 ...

  8. [Golang学习笔记] 02 命令源码文件

    源码文件的三种类型: 命令源文件:可以直接运行的程序,可以不编译而使用命令“go run”启动.执行. 库源码文件 测试源码文件 面试题:命令源码文件的用途是什么,怎样编写它? 典型回答: 命令源码文 ...

  9. [原创]java WEB学习笔记02:javaWeb开发的目录结构

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  10. 类型和变量(C#学习笔记02)

    类型和变量 [C#类型和变量(原文参考官方教程)]https://docs.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/types-and-var ...

随机推荐

  1. JavaScript浏览器对象模型(BOM)之window对象

    一.BOM概述 BOM(Browser Object Model)浏览器对象模型,它提供了很多对象,用于访问浏览器的功能. BOM 缺少规范,每个浏览器提供商又按照自己想法去扩展它,那么浏览器共有对象 ...

  2. keepalived.md

    配置文件说明 global_defs区域 global_defs { notification_email { acassen@firewall.loc failover@firewall.loc s ...

  3. android中反射技术使用实例

    在计算机科学领域.反射是指一类应用,它们能够自描写叙述和自控制.也就是说,这类应用通过採用某种机制来实现对自己行为的描写叙述(self-representation)和监測(examination), ...

  4. codeforces A. Supercentral Point 题解

    版权声明:本文作者靖心,靖空间地址:http://blog.csdn.net/kenden23/,未经本作者同意不得转载. https://blog.csdn.net/kenden23/article ...

  5. urllib库基本使用

    #导入urllib库 import urllib.request #打开网址 file=urllib.request.urlopen("http://www.sohu.com/", ...

  6. OpenGL之位图的绘制和gluOrtho2D等函数详解

    位图绘制 先来段代码吧: #include <iostream> #include <gl/glut.h> using namespace std; #pragma comme ...

  7. Java 今天是否为节假日

    /** * 测试今天是不是节假日 * 创建日期:2017年8月30日上午10:00:41 * 修改日期: * 作者:zhangsp * TODO * return */ public void wor ...

  8. How RTT works

    13.2 How RTT works 13.2.1 Target implementation Real Time Terminal uses a SEGGER RTT Control Block s ...

  9. Centos 7安装Grafana 4及结合Zabbix3.2实现可视化监控图形

    上一篇介绍了如何在Centos 7环境下安装zabbix监控,本章继续介绍在Centos 7环境下安装Grafana,并结合Zabbix实现可视化监控图形! 简介: Grafana 是 Graphit ...

  10. 纯 js 实现上传文件支持拖拽

    开发「bufpay.com 个人即时到账收款平台」 后台需要支持开发者的微信和支付宝二维码上传. <p> <button class="btn btn-primary&qu ...