[Go]程序实体
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]程序实体的更多相关文章
- [Golang学习笔记] 05 程序实体2 作用域访问权限和变量重声明
作用域访问权限: 程序实体访问权限(作用域)有三种:1. 包级私有(代码包)2. 模块级私有(代码包)3. 公开(全域). 一个函数是一个代码块.一个程序实体的作用域总是会被限制在某个代码块中.好处: ...
- [Golang学习笔记] 04 程序实体1 变量声明
变量声明: Go语言的程序实体包含:变量.常量.函数.结构体和接口,是一门静态类型的编程语言. (在声明变量或常量的时候,需要指定类型,或者给予足够信息是的Go语言能够推导出类型) Go语言变量的类型 ...
- MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致
MyBatis系列二 之 数据库列名于程序实体类中字段名称不一致 情景:当数据库中的列名与我们程序实体类中的字段名称不一致 使用ResultMap节点配置信息 在映射文件中 ...
- [Golang学习笔记] 06 程序实体3 类型断言和类型转换
类型断言: 语法:<目标类型的值>,<布尔参数> := <表达式>.( 目标类型 ) // 安全类型断言<目标类型的值> := <表达式>. ...
- 应用程序框架实战三十四:数据传输对象(DTO)介绍及各类型实体比较
本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行比较. 领域实体为何不能一统江湖? 当你阅读 ...
- 数据传输对象(DTO)介绍及各类型实体比较
数据传输对象(DTO)介绍及各类型实体比较 本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行 ...
- C++ 元编程 —— 让编译器帮你写程序
目录 1 C++ 中的元编程 1.1 什么是元编程 1.2 元编程在 C++ 中的位置 1.3 C++ 元编程的历史 2 元编程的语言支持 2.1 C++ 中的模板类型 2.2 C++ 中的模板参数 ...
- 在C#/.NET应用程序开发中创建一个基于Topshelf的应用程序守护进程(服务)
本文首发于:码友网--一个专注.NET/.NET Core开发的编程爱好者社区. 文章目录 C#/.NET基于Topshelf创建Windows服务的系列文章目录: C#/.NET基于Topshelf ...
- Microsoft Orleans构建高并发、分布式的大型应用程序框架
Microsoft Orleans 在.net用简单方法构建高并发.分布式的大型应用程序框架. 原文:http://dotnet.github.io/orleans/ 在线文档:http://dotn ...
随机推荐
- 491 Increasing Subsequences 递增子序列
给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2.示例:输入: [4, 6, 7, 7]输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, ...
- 在 Windows 7 中禁用IPv6协议/IPv6隧道
How to disable certain Internet Protocol version 6 (IPv6) components in Windows Vista, Windows 7 and ...
- poj3204Ikki's Story I - Road Reconstruction(最大流求割边)
链接 最大流=最小割 这题是求割边集 dinic求出残余网络 两边dfs分别以源点d找到可达点 再以汇点进行d找到可达汇点的点 如果u,v为割边 那么s->u可达 v->t可达 并且为饱 ...
- VS2015调用低版本lib库出现“无法解析的外部符号 __snprintf ”问题的解决
VS2015在调用低版本lib库出现有时会出现“无法解析的外部符号 __snprintf ”的问题,解决方法是加入lib库“legacy_stdio_definitions.lib”到工程.
- MSComDlg.CommonDialog服务器不能创建对象错误的解决
作者:朱金灿 来源:http://blog.csdn.net/clever101 在JavaScript中弹出打开文件对话框,代码如下: var fileOpenDlg = new ActiveXOb ...
- Linux常用终端快捷键
UNIX程序员对键盘以及快捷键的设置都遵循一个标准:"手移动最少的距离,作更多的操作." 所有的类UNIX的终端上都有一些快捷键Ctrl+n = 下,Ctrl+b = 左,Ctrl ...
- 【转】windows server 2012 安装 VC14(VC2015) 安装失败解决方案
系统环境如下:cmd命令行-输入 systeminfo 如下图 - The VC14 builds require to have the Visual C++ Redistributable for ...
- ftp 报错 200 Type set to A
最近在使用ssis 从ftp服务器抓起文件到本地的时候,发现连接ftp出错 200 Type set to A 解决办法: ftp connection 中 设置UsePassiveMode 为Tru ...
- (转)@Autowire注解与自动装配
http://blog.csdn.net/yerenyuan_pku/article/details/52860713 前面我们已经学会使用@Resource注解注入属性,并且我们还编码剖析了@Res ...
- liunx+mysql数据库管理
源码安装 查询是否安装: rpm -aq |grep mysql 1.下载yum 源 wget 'https://dev.mysql.com/get/mysql57-commu ...