[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 ...
随机推荐
- 492 Construct the Rectangle 构建矩形
详见:https://leetcode.com/problems/construct-the-rectangle/description/ C++: class Solution { public: ...
- ES6学习笔记(8)----对象的扩展
参考书<ECMAScript 6入门>http://es6.ruanyifeng.com/ 对象的扩展 1.属性名的简洁表示法 : ES6允许在代码中直接写变量,变量名是属性名,变量值是属 ...
- RxJava尝试取代Handler初探
在之前的一篇文章中,我们探究了RxJava的使用方法,详细请看https://www.cnblogs.com/yanyojun/p/9745675.html 根据扔物线大神的描述,如果用一个词来概括R ...
- windows.old文件删除
在安装完新系统后,会发现C盘下有个windows.old文件夹,大约有个10多G,里面都是对之前系统的一些备份,用于对之前系统恢复时使用,一般一个月后会自动清理,若觉得不会再对系统进行老版本恢复时,又 ...
- COGS 942. [東方S3] 比那名居天子
Problem 1 比那名居天子(tenshi.cpp/c/pas) 题目描述 在幻想乡,比那名居天子是管理着『要石』的天人.『要石』是能够引发和镇压地震的存在,当然也可以用来改变地形.因为在幻想乡引 ...
- 11gR2新特性---gipc守护进程
在这篇文章中,我们会对11gR2 新的守护进程gipcd(资源名称ora.gipcd)进行介绍,其中包括gipc的功能,启动顺序和一些基本的测试. 我们知道,对于oracle集群来说,集群私网是非常重 ...
- 深度剖析 MySQL 事务隔离
概述 今天主要分享下MySQL事务隔离级别的实现原理,因为只有InnoDB支持事务,所以这里的事务隔离级别是指InnoDB下的事务隔离级别. 隔离级别 读未提交:一个事务可以读取到另一个事务未提交的修 ...
- 数据库sql语句limit区别
注意:并非所有的数据库系统都支持 SELECT TOP 语句. MySQL 支持 LIMIT 语句来选取指定的条数数据, Oracle 可以使用 ROWNUM 来选取. SQL Server / MS ...
- 【搜索】P1019 单词接龙
题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...
- TWaver3D直线、曲线、曲面的绘制
插播一则广告(长期有效) TWaver需要在武汉招JavaScript工程师若干 要求:对前端技术(JavasScript.HTML.CSS),对可视化技术(Canvas.WebGL)有浓厚的兴趣 基 ...