Go语言中的程序实体包括变量、常量、函数、结构体、接口

1、常见声明变量的方式

 package main

 import (
"flag"
"fmt"
) func main() {
/* 第一种方式
var name string
flag.StringVar(&name, "name", "everyone", "The greeting object")*/ /* 第二种方式,利用go语言自身的类型推断省去了string
var name = *flag.String("name", "everyone", "The greeting object")*/ /* 第三种方式,短变量声明
name := *flag.String("name", "everyone", "The greeting object")*/ flag.Parse()
fmt.Printf("Hello, %v!\n", name)
}

2、go语言类型推断的好处

  可以明显提升程序的灵活性,似的代码重构变得更加容易,同时又不会给代码维护带来额外的负担,更不会损失程序的运行效率

可以先看一段代码

package main

import (
"flag"
"fmt"
) func getTheFlag() *string {
return flag.String("name","everyone", "The greeting object")
}
func main() {
var name = getTheFlag()
flag.Parse()
fmt.Printf("Hello, %v!\n", *name)
}

  我们可以用getTheFlag函数包装那个对flag.String函数的调用,并把其结果直接作为getTheFlag函数的结果,结果的类型是*string。这样一来,var name = 右边的表达式可以变为针对getTHRFlag函数的调用表达式,这实际上是对声明并赋值name变量的那行代码的重构(不改变某个程序与外界的任何交互方式和规则,而只改变其内部实现”的代码修改方式)。因此可以随意改变getTheFlag函数内部实现及其返回结果类型,而不用修改main函数中的任何代码,这是程序灵活性的质变。可以不显式地指定变量name的类型,使得它可以被赋予任何类型的值。也就是说,变量name的类型可以在其初始化时由其他程序动态决定。当改变getTheFlag函数的结果类型以后,Go语言的编译器会在你再次构建该程序时自动地更新变量name的类型

  Go语言是静态类型的,所以一旦初始化变量时确定了它的类型,这种类型的确定是在编译期完成的,因此不会对程序运行效率产生任何影响

3、变量重声明

  通过使用短变量声明,可以对同一代码块((花括号括起来的区域)中的变量进行重声明(对已经声明过得变量再次声明)。它允许我们在使用短变量声明时不用理会被赋值的多个变量中是否包含旧变量

  变量重声明的前提条件如下:

  1、由于变量的类型在其初始化时就已经确定了,所以对它再次声明时赋予的类型必须与其原本的类型相同,否则会产生编译错误

  2、变量重声明只可能发生在某一段代码块中,如果与当前变量重名的是外层代码块中的变量,那么就是另外一种含义了

  3、变量的重声明只有在使用短变量声明时才会发生,否则也无法通过编译

  4、被声明并赋值的变量必须是多个,并且其中至少有一个是新的变量

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

4、不同代码块的重名变量

  先看如下代码 

 package main

 import "fmt"

 var block = "package"
func main() {
block := "function"
{
block := "inner"
fmt.Printf("The block is %s.\n",block)
}
fmt.Printf("The block is %s.\n",block)
} //执行结果
//The block is inner.
//The block is function.

  这个命令源码文件中国有四个代码块,它们是:全域代码块、mai包代表的代码块、main函数代表的代码块,以及在main函数中的一个花括号包起来的代码块。在后三个代码块中分别声明了一个名为block的变量,并分别赋值

  从执行的结果看,对于不同的代码块来说,即使这些代码块有着直接嵌套关系,变量重名照样可以通过编译。

  那当变量重名时引用变量的时候到底用哪一个呢?

    1)代码引用变量的时候总会最优先查找当前代码块中的那个变量,注意这里的当前代码块仅仅是引用变量的代码所在的那个代码块,并不包含任何子代码块

    2)如果当前代码块中没有声明以此为名的变量,那么程序会沿着代码块的嵌套关系,从直接包含当前代码块的那个代码块开始,一层一层地查找

    3)一般情况下,程序会一直查到当前代码包代表的那层代码块,如果仍然找不到,那么Go语言的编译器就会报错了

  有个特殊情况,如果代码包导入语句写成import . xxx的形式,那么就会让“xxx”包中公开的程序实体视为当前代码包中的程序实体,在这个特殊情况下,程序在查找当前源码文件后悔先去查用这种方式导入的那些代码包

5、不同代码块中的重名变量与变量重声明变量的区别

  1)变量重声明的变量一定是在某一代码块内的(不包含任何其他子代码块)

  2)变量重声明是对同一个变量的多次声明,这里变量只有一个。而重名变量中能够涉及的变量肯定有多个

  3)不论对变量重声明多少次,其类型必须始终保持一致,具体遵从它第一次被声明时给定的类型。而重名变量之间不存在类似的限制,它们的类型可以是任意的

  4)如果重名变量所在代码块之间存在直接或间接的嵌套关系,那么它们之间一定存在“屏蔽”的现象,但这种现象一定不会在变量重声明中出现

6、如何判断一个变量的类型

 package main

 import "fmt"

 var container  = []string{"zero", "one", "two"}

 func main() {
container := map[int]string{: "zero", : "one", : "two"}
fmt.Printf("The element is %q.\n", container[])
}

  对以上代码,怎样在打印其中元素之前正确判断变量container的类型呢?

  答案是使用类型表达式,类型表达式的格式是x.(T),其中的x代表要被判断类型的那个值,这个值当下的类型必须是接口类型,不过具体是哪个接口类型是无所谓的

value ok := interface{}(container).([]string)

  这里interface{}(container)用来把container变量的值转换为空接口值,空接口interface{}代表了不包含任何方法定义的空的接口类型

  .([]string)用于判断前者的类型是否为切片类型,圆括号中[]string是一个类型字面量,类型字面量就是用来表示数据类型本身的若干字符(String 是表示字符串类型的字面量)

7、类型转换规则中需要注意的地方

  类型转换表达式的语法形式是T(x),其中x是一个变量,也可以是一个代表值的字面量,还可以是一个表达式(如果是表达式,那么表达式的结果只能有一个值)

  在这个上下文中,x可以被叫做源值,它的类型就是源类型,T代表的类型是目标类型

  1)对于整数类型值,整数常量之间的类型转换,原则上只要源值在目标类型的可表示范围内就是合法的

    var srcINT = int16(-)
dstInt := int8(srcINT)

  如上面的代码,把值类型从int16转换到int8

  2)虽然直接把整数值转换为一个string类型的值时可行的,但是被转换的整数值应该可以代表一个有效的Unicode代码点,否则转换的结果将会是仅由高亮的问号(�,专用于替换未知的,不被认可的以及无法展示的字符)组成的字符串值

  3)关于string类型与各种切片类型之间的互转

    a、一个值在从string类型向[]byte类型转换时代表着以UTF-8编码的字符会被拆分成零散、独立的字节

    b、 一个值从string类型向[]rune类型转换时代表着字符串会被拆分成一个个Unicode字符

8、别名类型和潜在类型  

type MyString = string

  MySting是string类型的别名类型,其与源类型除名字外其余一律相同

  byte是uint8的别名类型,rune是int32的别名类型

type MyString2 string //注意这里没有等号

  这是MyString2和string就是两个不同的类型了,这里的MyString2是一个新类型,不同于其他任何类型,这种方式也叫做对类型的再定义。string类型可以被称为MyString2的潜在类型。

  潜在类型的含义是某个类型在本质上是哪个类型或者哪个类型的集合

  潜在类型相同的不同类型的值之间是可以进行类型转换的,因此MyString2类型的值与string类型的值可以使用类型转换表达式进行互转

  但对于集合类的类型[]MyString2与[]string来说这样做却是不合法的,因为[]MyString2与[]string的潜在类型不同,分布是MyString2和string

  另外,即使两个类型的潜在类型相同,它们的值之间也不能进行判等或比较,它们的变量之间也不能赋值

[Go]程序实体的更多相关文章

  1. [Golang学习笔记] 05 程序实体2 作用域访问权限和变量重声明

    作用域访问权限: 程序实体访问权限(作用域)有三种:1. 包级私有(代码包)2. 模块级私有(代码包)3. 公开(全域). 一个函数是一个代码块.一个程序实体的作用域总是会被限制在某个代码块中.好处: ...

  2. [Golang学习笔记] 04 程序实体1 变量声明

    变量声明: Go语言的程序实体包含:变量.常量.函数.结构体和接口,是一门静态类型的编程语言. (在声明变量或常量的时候,需要指定类型,或者给予足够信息是的Go语言能够推导出类型) Go语言变量的类型 ...

  3. MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致

    MyBatis系列二  之   数据库列名于程序实体类中字段名称不一致 情景:当数据库中的列名与我们程序实体类中的字段名称不一致         使用ResultMap节点配置信息  在映射文件中  ...

  4. [Golang学习笔记] 06 程序实体3 类型断言和类型转换

    类型断言: 语法:<目标类型的值>,<布尔参数> := <表达式>.( 目标类型 ) // 安全类型断言<目标类型的值> := <表达式>. ...

  5. 应用程序框架实战三十四:数据传输对象(DTO)介绍及各类型实体比较

    本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行比较. 领域实体为何不能一统江湖? 当你阅读 ...

  6. 数据传输对象(DTO)介绍及各类型实体比较

    数据传输对象(DTO)介绍及各类型实体比较 本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行 ...

  7. C++ 元编程 —— 让编译器帮你写程序

    目录 1 C++ 中的元编程 1.1 什么是元编程 1.2 元编程在 C++ 中的位置 1.3 C++ 元编程的历史 2 元编程的语言支持 2.1 C++ 中的模板类型 2.2 C++ 中的模板参数 ...

  8. 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)

    本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...

  9. Microsoft Orleans构建高并发、分布式的大型应用程序框架

    Microsoft Orleans 在.net用简单方法构建高并发.分布式的大型应用程序框架. 原文:http://dotnet.github.io/orleans/ 在线文档:http://dotn ...

随机推荐

  1. P3374 【模板】树状数组 1 单点修改与区间查询

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  2. web前端工程师入门须知

    本文是写给那些想要入门web前端工程的初学者,高手请路过,也欢迎高手们拍砖. 先说下web前端工程师的价值,目前web产品交互越来越复杂,用户使用体验和网站前端性能优化这些都得靠web前端工程师去做w ...

  3. Nagios的服务器监控

    第一部分是主机外监控,比如:主机是否存活,WEB服务是否正常,MySQL服务是否正常等内容,再主机外通过访问其端口即可得知.这些监控命令再安装nagios-plugins-1.4.13.tar.gz时 ...

  4. SQL——将两列合并成一列

    将两列合并连接成一列,需要注意的是列的格式必须是NVARCHAR或者VARCHAR类型 ), call_uuid, ) +','+agent_code '   PerDate 1 ,980408102 ...

  5. MVC之在实例中的应用

    MVC模式在Java Web应用程序中的实例分析 1. 结合六个基本质量属性 1)可用性 2)可修改性 3)性能 4)安全性 5)可测试性 6)易用性 2. 分析具体功能模块的MVC设计实现(例如登录 ...

  6. Oracle数据库升级前必要的准备工作

    Oracle数据库升级向来是一门纷繁复杂的工程,DBA需要为产品数据库的升级耗费大量时间精力在准备工作上:因为其升级复杂度高,所以即便做了较为充分的准备仍可能在升级过程中遇到意想不到的问题,为了更高效 ...

  7. (转)使用Spring配置文件实现事务管理

    http://blog.csdn.net/yerenyuan_pku/article/details/52886207 前面我们讲解了使用Spring注解方式来管理事务,现在我们就来学习使用Sprin ...

  8. 初次改app

    没有学过安卓,突然需要改app里的一个bug,一个没搞过安卓的人要怎么入手去改这个安卓的代码呢?下面看看我入手的步骤 首先,页面上有几个文字“曲线分析”,那么在项目里找到这个文字,就可以找到这个页面的 ...

  9. SQA定义、质量模型、SQA与测试的关系

  10. NetBeans 默认编码修改方法

    如果要NetBeans用UTF-8对文件进行解码,需要修改配置文件,具体方法如下: 1. 找到你的Netbeans安装目录下的etc文件夹,如D:\Program Files\NetBeans 8.2 ...